-4

如果我们有一个ConcurrentBag<object>装满 100 个对象的 safeBag`。

然后一个线程工作为:

   foreach(object o in safeBag)
{
    Thread.Sleep(1000);
}

另一个线程在第一个线程启动后立即启动:

{
    safeBag.AddOrTake(something);
}

第二个线程会等待 100 秒进入资源吗?另一个问题,如果第一个线程使用 Parallel.ForEach() 运行,线程将如何工作?

编辑:MSDN 说:“一个列表可以同时支持多个读取器,只要不修改集合。通过集合枚举本质上不是线程安全的过程。在极少数情况下,枚举与一个或多个写入竞争访问,确保线程安全的唯一方法是在整个枚举期间锁定集合。” 通过 ConcurrentBag 进行枚举是否会导致第二个线程等待对 ConcurrentBag 的写入访问?

4

2 回答 2

2

对于大多数Concurrent*集合,大多数操作都是原子的,但不持有任何长期锁。返回后第一个线程不会阻塞第二个线程GetEnumerator()

ConcurrentBag<T>.GetEnumerator方法

枚举表示包内容的即时快照。它不反映调用 GetEnumerator 后对集合的任何更新。枚举器可以安全地与对包的读取和写入同时使用。

于 2012-10-26T09:48:08.187 回答
0

第二个线程,假设您连续生成两个线程 - 第一个使用ThreadStart指向包含迭代的块,第二个指向另一个代码块,不会等待 1000 毫秒。该foreach块将在移动到集合中的下一个对象之间仅等待 1 秒,第二个块不受此影响。

如果它是一个并行的 foreach,那么在移动到下一个元素之前,您将有几个线程(同时)等待一秒钟。第二个块仍然不会等待ConcurrentBag变得空闲。

于 2012-10-26T09:14:15.480 回答