我有一个ConcurrentDictionary,它将简单类型映射到列表:
var dict = new ConcurrentDictionary<string, List<string>>();
当添加第一个值时,我可以使用AddOrUpdate()满足列表的初始化,以及将后续值添加到列表中。
但是,删除操作并非如此。如果我做类似的事情:
public void Remove(string key, string value)
{
List<string> list;
var found = dict.TryGetValue(key, out list);
if (found)
{
list.Remove(value);
if (list.Count == 0)
{
// warning: possible race condition here
dict.TryRemove(key, out list);
}
}
}
...我的目的是如果对应列表不再具有任何值,则完全删除密钥(类似于概念上的引用计数),那么我冒着竞争的风险,因为有人可能会在我检查是否为空后立即将其添加到列表中。
尽管在此简单示例中使用的是列表,但在这种情况下,我通常会有一个ConcurrentBag或ConcurrentDictionary,并且风险非常相似。
当相应的集合为空时,有什么方法可以安全地删除密钥,而无需借助锁?
您的ConcurrentDictionary
受保护,但您的列表不受保护。如果可以从多个线程访问列表(我假设是这种情况),则需要对列表的所有访问使用锁定,或者需要使用其他构造。
我最近研究了同一主题,并在the newer version of this question中找到了更好的解决方案。