我试图了解集合ConcurrentBag<T>和List<T>本文之间的区别。
出于某种原因,在我看来,如果我使用List<T>它并且当一个线程在那里写一些东西并尝试对另一个线程做同样的事情时,会弹出一个异常,但不,一切正常。
我的剧本
有一种多线程处理场景,在其工作结束时,所有线程必须将其结果写入一个集合:
class Program
{
static void Main(string[] args)
{
var results = new List<string>();
//var results = new ConcurrentBag<string>();
// STEP 1: Get results.
Parallel.For(1, 50000, idx =>
{
// Some process.
//...
results.Add("something");
});
// STEP 2: Process results.
foreach (var result in results)
{
//...
}
}
}
问题
ConcurrentBag<T>我在用例中而不是List<T>在我的案例中获得什么优势?
还有一个小问题:results称它为共享资源是否正确?
问题可能会发生,也可能不会发生。这被称为线程不安全集合 - 当问题可能出现时。今天它工作,明天它会下降 - 因为不能保证在并行工作时,2个线程不会尝试同时写入列表。
您有一个列表的事实
Parallel.For并不能保证并行访问。并发访问是指 2 个或更多线程尝试在同一时间单位内对列表进行操作。在您的情况下,在第一次、第二次、第三次启动期间,这可能不会发生,但在第 99 次启动时,代码会下降。多线程
如果您选择,
ConcurrentBag<T>您将获得保证您的代码不会在多线程工作中崩溃。使用时List<T>没有任何保证,甚至不能保证不会丢失数据,也不能保证不会出现异常。我再说一遍——即使是相同的多线程代码也可以在 99 种情况下工作,并且在使用线程不安全的集合时会在 1 种情况下崩溃。既然线程共享它,那么是的
在您的具体代码中,我个人不认为共享资源有什么意义,这样写要容易得多:
List<T>不是线程安全的。这意味着当从不同的线程访问数据时,它根本不采取任何措施来保护数据。没有锁,甚至没有并发检查。你不会得到例外,但你也不会得到数据完整性保证。利用
ConcurrentBag<T>