检查多线程应用程序的集合中是否存在元素
本文关键字:是否 存在 元素 集合 多线程 应用程序 检查 | 更新日期: 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))
{
}
}