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

本文关键字:是否 存在 元素 集合 多线程 应用程序 检查 | 更新日期: 2023-09-27 18:35:46

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

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
}

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

你应该使用 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 块中使用锁。

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

// 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))
    {
    }
}