You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ConcurrentBag初始为null时Parallel.ForEach添加元素异常问题

问题:ConcurrentBag初始为null时,Parallel.ForEach无法正确添加元素?

测试场景

场景1:初始为null的情况

ConcurrentBag<string> test = null;
List<string> list= new() { "1", "2", "3", "2", "3", "2", "3", "2", "3", "2",
    "3", "2", "3", "2", "3", "2", "3", "2", "3", "2", "3", "2", "3" };
Parallel.ForEach(list, x => { (test ??= new()).Add("result"); });

调试时test的元素数量每次不同(如19/23个)。

场景2:提前实例化的情况

ConcurrentBag<string> test = new();
List<string> list= new() { "1", "2", "3", "2", "3", "2", "3", "2", "3", "2",
    "3", "2", "3", "2", "3", "2", "3", "2", "3", "2", "3", "2", "3" };
Parallel.ForEach(list, x => { (test ??= new()).Add("result"); });

test始终有23个元素。

原因分析

问题出在test ??= new()这个操作上——它不是原子操作。

当多个线程并行执行时,可能会有多个线程同时判断test为null,然后各自创建新的ConcurrentBag<string>实例。这些线程会把"result"添加到自己创建的那个实例里,但最终只有最后一个完成赋值操作的实例会覆盖test变量。其他线程创建的实例因为没有被引用,里面的元素也就丢失了,这就导致最终test里的元素数量每次都不一样(取决于有多少线程各自创建了实例)。

而场景2中,test一开始就被实例化为同一个ConcurrentBag对象,所有线程都操作这个唯一的线程安全容器,Add方法本身是线程安全的,所以23个元素能全部正确添加进去。

内容的提问来源于stack exchange,提问作者Trekki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:12:42