【发布时间】:2014-12-04 15:07:47
【问题描述】:
我有一个 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 ,并且风险非常相似。
当相应的集合为空时,有什么方法可以安全地移除密钥,而不是求助于锁?
【问题讨论】:
-
调用
TryGetValue和Remove之间是否也存在潜在的竞争? -
我可能是错的,但我不这么认为...如果有人在空性检查之前添加了一些东西,那么它就不会是空的...
-
如果他们调用remove怎么办?
-
如果同时删除两件事,然后其中一个发现列表为空并将其删除,这是预期的行为。真正的危险是由于竞争条件而丢失了一个非空列表。
标签: c# concurrency race-condition concurrentdictionary