字典作为线程安全的变量

Zav*_*ael 3 c# static dictionary thread-safety

我有一个类(单例),它包含一个静态字典

private static Dictionary<string, RepositoryServiceProvider> repositoryServices = null;
Run Code Online (Sandbox Code Playgroud)

在这个类的实例中我填充字典(可以从多个线程发生).起初我只是

        RepositoryServiceProvider service = null; 
        repositoryServices.TryGetValue(this.Server.Name, out service);
        if (service == null) {
          service = new RepositoryServiceProvider(this.Server);
          repositoryServices.Add(this.Server.Name, service);  
        }
Run Code Online (Sandbox Code Playgroud)

然后我有一些例外,因为Item已添加,所以我将其更改为:

        RepositoryServiceProvider service = null;    
        repositoryServices.TryGetValue(this.Server.Name, out service);
        if (service == null) {
          lock (padlock) {
            repositoryServices.TryGetValue(this.Server.Name, out service);
            if (service == null) {
              service = new RepositoryServiceProvider(this.Server);
              repositoryServices.Add(this.Server.Name, service);  
            }
          }
        }
Run Code Online (Sandbox Code Playgroud)

和挂锁在课堂上:

private static readonly object padlock = new object();
Run Code Online (Sandbox Code Playgroud)

这个线程安全吗?还是过于复杂?或者我应该使用ConcurentDictionary

Yah*_*hia 8

如果您可以使用ConcurrentDictionary- 它在几种情况下比您的方法更快,因为它在线程安全的同时实现了大多数无锁操作.

编辑 - 根据评论:

"大多数操作无锁"这个词有点过于笼统......

基本上它意味着减少争用...因此在某些情况下与具有一个全局锁定的情况相比更高效,即在第一个存储桶被锁定时访问第二个存储桶就好像没有来自访问代码的POV的锁定一样.虽然这意味着该桶的本地锁定...在实际应用程序中,它提供了比全局锁定更好的性能 - 尤其是.多核.

  • 无锁线程安全集合是程序员相当于永久移动的."看不到锁"并不意味着无锁. (3认同)
  • @Yahia:据我所知,对于`CD <K,V>`没有任何锁定:大多数操作都需要锁定,但它使用某种条带化 - 每桶一锁,即iirc - 以减少争用.当然,一些操作 - 例如,调整内部阵列的大小 - 仍然需要取出全局锁定以保证一切安全. (2认同)