假设我们有两个线程和一个集合:
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
}
答案 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))
{
}
}