c# - ConcurrentDictionary 和原子操作——有时需要 Lock 吗?

标签 c# multithreading .net-4.0 concurrentdictionary

假设我有这个简单的代码:(简化)

在哪里MyConCurrentDictionary是静态的 ConcurrentDictionary<string, string> (属于不同的类)。

/*1*/   public void Send(string Message, string UserName)
/*2*/   {            
/*3*/       string ConnectionId;
/*4*/       if (MyConCurrentDictionary.TryGetValue(UserName,out ConnectionId))
/*5*/       {
/*6*/       //...   
/*7*/           DB.InsertMessage( Message, ConnectionId);
/*8*/           LOG.LogMessage  ( Message, ConnectionId);
/*9*/       //...
/*10*/       }
/*11*/       else ...
/*12*/   }

此方法从许多实例运行。 (signalR hub,如果你愿意的话)

我需要插入 DB/log 如果 user/connectionID存在。

行了 #4当多线程访问 ConcurrentDictionary 时是线程安全的

但还有另一种方法是 RemoveUser - 从字典中删除用户:

 public void RemoveUser (string userName)
        {
           string removed;
           if ( MyConCurrentDictionary.TryRemove(userName,out removed ))
              Clients.All.removeClientfromChat(userName);
        }

但上下文有可能出现在 #5 行这会做 RemoveUser并从 ConcurrentDictionary 中删除用户名。

所以为了解决这个问题——代码应该是这样的:

lock(locker)
{
  if (MyConCurrentDictionary.TryGetValue(UserName,out ConnectionId))
   {
    //...
   }

}

这完全打败了我的 ConcurrentDictionary 的目的.

问题

在多线程环境中做这样的事情的正确方法是什么 - 仍然有 ConcurrentDictionary 的好处?

nb ,是的,ConcurrentDictionary 仅对字典内的操作是线程安全的。但我想说的是,在特定情况下,我失去了 ConcurrentDictionary 的好处,因为我仍然需要使用锁。(我可能错了)。

最佳答案

根据您所写的内容和我目前的理解:ConcurrentDictionary 不是合适的选择!

写一个类,封装一个普通的Dictionary,通过ReaderWriterLockSlim封装读写操作。这比普通锁要快得多。您也可以同时进行多次读取但一次只能进行一次写入操作。

private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

public void DoRead(string xyz)
{
    try
    {
        _lock.EnterReadLock();
        // whatever
    }
    finally
    {
        _lock.ExitReadLock();
    }
}

public void DoWrite(string xyz)
{
    try
    {
        _lock.EnterWriteLock();
        // whatever
    }
    finally
    {
        _lock.ExitWriteLock();
    }
}

关于c# - ConcurrentDictionary 和原子操作——有时需要 Lock 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23732280/

相关文章:

c# - Fluent NH 和接口(interface)映射

java - 安卓 : Thread not passing data to Handler

c# - 使用 linq 的存储库模式

c# - 使用 new() 或 default 初始化变量之间的区别?

c# - 反编译的 C# 代码中的 __methodptr

java - 来自不同线程的顺序文件 IO 失败并出现 FileSystemException

c# - 如何使用 async 和 await 正确处理

c# - ObservableCollection CollectionChanged 事件似乎没有触发——为什么?

c# - 从 LINQ 查询结果返回单个属性

c# - 在默认浏览器中重定向到 http 页面的 winforms 应用程序中的链接