5

假设我们有两个线程和一个集合:

ConcurrentDictionary<int, object[]> lists = new ConcurrentDictionary<int, object[]>();

1)一个线程处理集合中的元素,然后从集合中删除元素

foreach(object[] elem in lists.Values)
{
    //do somethind
    lists.TryRemove(key, out vals);
}

2)第二个线程将元素添加到集合中,然后它需要能够检查元素状态:

lists.Add(10, some_object);

...

if(lists.ContainsKey(10))
{

    //How can I be sure that at this moment element is still exists ?
    //Thread may be preempted after if() {} and second thread 
    //can remove object from collection
}
4

2 回答 2

7

您应该使用TryGetValue,因为这可以确保检查/获取是原子的:

object[] val;
if(lists.TryGetValue(10, out val)) {
    // Here you have a reference to the object[], even if it has subsequently been removed
}

当然,object[]自身的线程安全是另外一个问题,无法通过ConcurrentDictionary. (例如,如果说两个线程都以某种方式修改了对象,并且对象不是线程安全的,那么您需要在TryGetValue块内使用锁。)

于 2013-10-17T20:55:17.253 回答
0

在这种情况下,您将需要围绕访问字典的代码编写自己的锁定。那时,不再需要并发字典,因为您将在字典之外同步对它的访问,因此基本上是重复工作。

// in thread 1
lock(COMMON_LOCK_OBJECT)
{
   foreach(object[] elem in lists.Values)
   {
     //do somethind
     lists.TryRemove(key, out vals);
   }

}

线程 2 中的一个:

lock(COMMON_LOCK_OBJECT)
{
    lists.Add(10, some_object);

    ...

    if(lists.ContainsKey(10))
    {

    }
}
于 2013-10-17T20:55:26.837 回答