检查多线程应用程序中的集合中是否存在元素

时间:2013-10-17 20:51:14

标签: c# multithreading

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

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
}

2 个答案:

答案 0 :(得分:5)

您打算使用TryGetValue,因为这可以确保check / get是原子的:

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块内使用锁。)

答案 1 :(得分: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))
    {

    }
}