假设我有这个简单的代码:(简化)
在哪里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/