虽然目前的两个答案在技术上都是正确的,但我认为它们可能会产生一些误导,并且它们并没有表达 ConcurrentDictionary 的强大优势。也许 OP 解决锁问题的原始方法在特定情况下有效,但这个答案更普遍地针对第一次学习 ConcurrentDictionary 的人。
并发字典的设计使您不必使用锁。它有几种特殊的方法,围绕着这样的想法设计的,即当您当前正在处理字典中的对象时,一些其他线程可以修改字典中的对象。举个简单的例子,TryUpdate 方法可以让您检查一个键的值是否在您获得它和您尝试更新它的那一刻之间发生了变化。如果您获得的值与当前在 ConcurrentDictionary 中的值匹配,您可以更新它并且 TryUpdate 返回 true。如果不是,TryUpdate 将返回 false。TryUpdate 方法的文档可能会使这有点混乱,因为它没有明确说明为什么存在比较值,但这就是比较值背后的想法。如果您想对添加或更新进行更多控制,则可以使用AddOrUpdate 方法的重载之一来为键添加值(如果在您尝试添加它时它不存在)如果其他线程已经为指定的键添加了值,则更新该值。您尝试做的任何事情的上下文将决定使用适当的方法。关键是,与其锁定,不如尝试查看 ConcurrentDictionary 提供的特殊方法,并更喜欢那些尝试提出自己的锁定解决方案的方法。
对于 OP 的原始问题,我建议不要这样:
ConcurrentDictionary<Guid, Client> m_Clients;
Client client;
//Does this if make the contents within it thread-safe?
if (m_Clients.TryGetValue(clientGUID, out client))
{
//Users is a list.
client.Users.Add(item);
}
可以尝试以下方法*:
ConcurrentDictionary<Guid, Client> m_Clients;
Client originalClient;
if(m_Clients.TryGetValue(clientGUID, out originalClient)
{
//The Client object will need to implement IEquatable if more
//than an object instance comparison needs to be done. This
//sample code assumes that Client implements IEquatable.
//If copying a Client is not trivial, you'll probably want to
//also implement a simple type of copy in a method of the Client
//object. This sample code assumes that the Client object has
//a ShallowCopy method to do this copy for simplicity's sake.
Client modifiedClient = originalClient.ShallowCopy();
//Make whatever modifications to modifiedClient that need to get
//made...
modifiedClient.Users.Add(item);
//Now update the value in the ConcurrentDictionary
if(!m_Clients.TryUpdate(clientGuid, modifiedClient, originalClient))
{
//Do something if the Client object was updated in between
//when it was retrieved and when the code here tries to
//modify it.
}
}
*请注意,在上面的示例中,我使用 TryUpate 是为了便于演示该概念。在实践中,如果您需要确保在对象不存在时添加对象或在对象存在时更新对象,则 AddOrUpdate 方法将是理想的选择,因为该方法处理检查添加与更新所需的所有循环和采取适当的行动。
一开始可能看起来有点困难,因为可能需要实现 IEquatable ,并且根据需要复制 Client 实例的方式,某种复制功能,但从长远来看,如果你正在使用它,它会得到回报ConcurrentDictionary 和其中的对象以任何严肃的方式。