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

其中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集线器,如果可以的话)

我需要插入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中删除UserName。

因此,为了解决此问题-代码将如下所示:
lock(locker)
{
  if (MyConCurrentDictionary.TryGetValue(UserName,out ConnectionId))
   {
    //...
   }

}

这完全违背了ConcurrentDictionary的目的。

问题

在多线程环境中同时又受益于ConcurrentDictionary的正确方法是什么?

nb是,ConcurrentDictionary仅在字典中运行时才是线程安全的。但是我想说的是,在特定情况下,我失去了ConcurrentDictionary的好处,因为我仍然需要使用lock。(这可能是我错了)。

最佳答案

根据您所写的内容和我到目前为止所了解的内容: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();
    }
}

10-08 06:16