标签: syncroot

正确的方法来锁定字典对象

在我的代码中,我有一个静态字典对象

private static IDictionary< ConnKey, DbConnection > ConnectionList = new Dictionary< ConnKey, DbConnection >( );
Run Code Online (Sandbox Code Playgroud)

这就是抛出这个错误

System.IndexOutOfRangeException: Index was outside the bounds of the array.
  at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
  at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
Run Code Online (Sandbox Code Playgroud)

我搜索并发现这是因为多个线程尝试访问字典,但我确实lock在字典上

lock( ConnectionList ) {
   ConnectionList.Add( key, res );
}
Run Code Online (Sandbox Code Playgroud)

然后我搜索了更多,发现字典上的锁并没有阻止它上面的所有操作,所以我应该像这样使用lock它的SyncRoot对象来实现我想要的

lock( ((IDictionary)ConnectionList).SyncRoot) {
Run Code Online (Sandbox Code Playgroud)

但后来我搜索到使用SyncRoot不是一个好习惯

在进一步搜索中,我发现有一个ConcurrentDictionary用于此目的

  1. 那么任何人都可以建议我哪个是锁定字典的最佳方法
  2. 如果我使用ConcurrentDictionary,我仍然需要使用lock它或它将自己处理一切.
  3. 如果我必须使用锁定ConcurrentDictionary,我必须lock直接或再次使用它我必须SyncRoot为它锁定对象

提前致谢!

c# multithreading dictionary locking syncroot

16
推荐指数
1
解决办法
1万
查看次数

为什么要锁定Collection.SyncRoot而不是只锁定集合?

我试图理解ICollection中syncroot的意义.为什么不直接锁定集合?

lock(myCollection)
{
    //do stuff to myCollection
}
Run Code Online (Sandbox Code Playgroud)

VS

lock(myCollection.SyncRoot)
{
    //do stuff to myCollection
}
Run Code Online (Sandbox Code Playgroud)

.net icollection syncroot

6
推荐指数
1
解决办法
5060
查看次数

SyncRoot对象真的是线程安全的吗?

我是SyncRoot概念的新手.据我所知,用于锁定的对象应该是私有的.

但是HashTable有一个公共属性,SyncRoot它只是一个私有SyncRoot对象的包装器.它建议你锁定HashTable.SyncRoot枚举该集合的时候.

看起来我们可能会失败,因为它不再是私有的.它真的是线程安全吗?

如果我制作自己的私人锁定机制怎么办? private readonly object _syncObject;

哪一个更好,为什么?

c# multithreading thread-safety syncroot

3
推荐指数
2
解决办法
1931
查看次数

复制之前锁定整个词典或部分词典(SyncRoot)

我在 Blazor 服务器应用程序的范围服务中有 2 个字典,我用它来管理多租户的状态。我注意到用户在不同线程上修改字典可能存在并发问题。

public Dictionary<string, GlobalDataModel> Global { get; } = new();
public Dictionary<string, Dictionary<long, LocalDataModel>> Local { get; } = new();
Run Code Online (Sandbox Code Playgroud)

我想我倾向于将它们保留为普通字典并在修改或迭代时锁定同步根。

如果我要将一个项目添加到包含类中的集合中,它会是:

if (Local.ContainsKey(tenantId) == false)
{
    lock (syncRoot)
    {
        Local.Add(tenantId, new Dictionary<long, LocalDataModel>());
    }
}
Run Code Online (Sandbox Code Playgroud)

或者:

lock (syncRoot)
{
    if (Local.ContainsKey(tenantId) == false)
    {
        {
            Local.Add(tenantId, new Dictionary<long, LocalDataModel>());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,如果我要将服务集合的不同部分从外部类复制到列表中,以便可以安全地迭代它,我是否只锁定在服务级别、字典级别或数据模型级别,或者它是依赖的?

假设我想要一个特定项目中的资源集合。可不可能是:

[Inject] private IDataAdaptor DataAdaptor { get; set; };
var resources;
    
lock (DataAdaptor)
{
    resources = DataAdaptor.Local[TenantId][ProjectId].Resources;
}
Run Code Online (Sandbox Code Playgroud)

或者:

lock (DataAdaptor.Local[TenantId][ProjectId].Resources)
{ …
Run Code Online (Sandbox Code Playgroud)

c# multithreading thread-safety syncroot blazor

2
推荐指数
1
解决办法
165
查看次数