在可能存在迭代器时替换并发集合是否是线程安全的?

时间:2015-02-04 17:15:13

标签: c# multithreading

我一直在阅读各种各样的东西,看起来这应该有用,但我想确定一下。我有一个静态属性,应该是一个缓存(加上一些与缓存数据相关的其他功能)。它将实际数据存储在ConcurrentBag中,它有一个IEnumerable方法来[过滤和]从这个包中产生返回值。它会像这样自我更新:

ConcurrentBag<Foo> NewBag = GetNewThings();
Cache = NewBag;

从我所读过的内容来看,这似乎应该有效,尽管我没有预料到这一点。我预计这会炸掉任何正在读取的迭代器。但是我读到如果另一个线程正在遍历旧列表,它将在新列表被交换时在列表的该实例上完成。第二个(新)线程将在新列表上启动,即使旧线程仍在迭代旧实例。这看起来很神奇,所以我可能错了,是吗?

其他线程只迭代列表,唯一的写入就是在这两行上进行的。

2 个答案:

答案 0 :(得分:3)

  

我读到如果另一个线程正在迭代旧列表,那么   当新列表获得时,将在列表的该实例上完成   交换。第二个(新的)线程将在新列表上开始,即使是   旧线程仍在迭代旧实例。这个   看起来很神奇,所以我可能错了,是吗?

你读的是正确的。

这是线程安全的,但您可能希望创建变量volatile或使用Volatile.ReadVolatile.Write以确保所有线程的即时可见性。

答案 1 :(得分:2)

分配给Cache的原始实例仍然存在,并且是旧线程迭代的实例。

新线程对GetNewThings()结果进行操作。