何时ConcurrentDictionary将TryRemove返回false

时间:2010-08-19 07:14:11

标签: c# .net concurrency

如果字典不包含给定键的值,它是否只返回false,或者由于线程竞争条件它也会返回false,就像另一个线程添加/更新某些东西一样?

代码中的问题:

ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>();

// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one"); 

// Will this ever fail if no other thread ever removes with the key value of 1?
cd.TryRemove(1); 

修改 我认为如果它不包含给定键的值,它只返回false,但是想要绝对确定。

3 个答案:

答案 0 :(得分:72)

虽然Mitch is right ConcurrentDictionary不容易受到竞争条件的影响,但我认为您要问的答案是肯定的,如果密钥存在,TryRemove将有效并将返回true

在您发布的代码中,TryRemove无法返回false,因为cd是一个其他地方无法访问的本地变量。但是如果其他地方的某些代码被赋予对这个ConcurrentDictionary对象的引用并且正在删除单独线程上的键,那么TryRemove可能会返回false,即使在这里 - 但是只是因为密钥已被删除,不是因为字典上正在执行某些其他操作而且密钥以某种方式“卡在”那里。

答案 1 :(得分:6)

ConcurrentDictionary没有受到竞争条件的影响。这就是你使用它的原因。

  

返回值

     

如果删除了某个对象,则为true   成功;否则,错误。

答案 2 :(得分:1)

要做的另一点:

// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one"); 

此评论不正确,可能会对“尝试”的含义产生同样的误解。它不是要同时添加的尝试,而是是否已使用键1添加了值。

考虑标准Dictionary<TKey,TValue>。等效代码为:

if (!d.Contains(1))
    d.Add(1, "one");

这需要两个操作。没有办法将这样的API设计为线程安全的,因为cd可能在调用1Contains之间添加了键Add的值,这会导致在Add投掷。

并发集合具有API,这些API在单个API后面逻辑地将这些测试 - 操作对捆绑到单个原子操作中。