C#.NET ConcurrentBag<T> 设计原理与使用场景

简介

ConcurrentBag<T>System.Collections.Concurrent命名空间下的线程安全的无序集合,专为 “多线程同时添加 / 移除元素” 设计,核心特点是基于线程局部存储(TLS)优化,在 “同一线程频繁添加和移除元素” 的场景下性能最优,是.NET中处理无序线程安全集合的核心工具。

核心定位与价值

在多线程场景中,普通的List<T>非线程安全(多线程操作会抛出异常或数据损坏),而lock包裹的List<T>存在锁竞争问题(性能低)。ConcurrentBag<T>的核心价值:

  • 无锁核心路径:通过线程局部存储(TLS)让每个线程优先操作自己的私有数据段,减少跨线程锁竞争;

  • 无序存储:不保证元素的顺序(插入顺序≠遍历顺序),牺牲顺序换取性能;

  • 线程安全:所有操作(Add/TryTake等)均线程安全,无需手动加锁;

  • 适配特定场景:尤其适合 “生产者和消费者为同一线程” 的场景(如线程池线程自产自销)。

核心特点

特性ConcurrentBagConcurrentQueueConcurrentStack典型使用场景
顺序保证无序(完全不保证)FIFOLIFO不关心顺序的场景
线程安全多线程并发
元素重复取出风险可能(同一个线程可能先取后放)不可能不可能允许“偷取”工作
内存使用较低(分段 + 线程本地袋)中等中等大量小对象
支持 Peek不支持支持支持
典型模式工作窃取(work-stealing)生产者-消费者后进先出任务栈并行任务池、负载均衡

内部实现原理

ConcurrentBag的高性能来源于线程本地存储 + 工作窃取的设计:

  • 每个线程拥有一个私有小袋(bag)(通常是链表或数组)

  • 线程Add/Take时优先操作自己的私有袋(几乎无锁)

  • 当自己袋子为空时,会去“偷”其他线程的袋子(work-stealing

  • 这种设计导致:

    • 同一个线程插入的元素,很可能被同一个线程先取出(局部性好)

    • 但跨线程看,完全无序,而且可能出现同一个元素被同一个线程先取后放的情况

  • 轻量级锁:仅在跨线程窃取元素时加锁,核心路径(同线程存取)无锁,性能远超全局锁的List<T>

工作窃取

工作窃取

工作窃取

线程A

本地队列A: 1, 3, 5

线程B

本地队列B: 2, 4

线程C

本地队列C: 6

全局队列

核心 API

核心构造函数
  • ConcurrentBag<T>(): 创建空的线程安全集合

  • ConcurrentBag<T>(IEnumerable<T>): 用指定集合初始化ConcurrentBag<T>

核心方法 / 属性
  • Add(T item): 向集合添加元素(线程安全),无返回值

  • TryTake(out T result): 尝试从集合移除并返回任意元素:成功返回true,集合为空返回false

  • Count: 获取集合中元素的数量(线程安全,但值为瞬时快照)

  • IsEmpty: 判断集合是否为空(线程安全,瞬时快照)

  • GetEnumerator(): 返回遍历集合的枚举器(遍历的是瞬时快照,不保证后续元素不变)

常用操作
varbag=newConcurrentBag<string>();// 插入(极快)bag.Add("任务A");bag.Add("任务B");// 尝试取出(非阻塞)if(bag.TryTake(outvaritem)){Console.WriteLine($"取出:{item}");}// 尝试偷取(TryPeek 不存在!)if(bag.TryTake(outvarstolen)){/* 处理 */}// 计数(注意:有一定开销)intcount=bag.Count;// 清空(不常用)bag.Clear();// 检查是否为空boolisEmpty=bag.IsEmpty;

用法示例

多线程添加与消费
usingSystem;usingSystem.Collections.Concurrent;usingSystem.Threading.Tasks;classConcurrentBagBasicDemo{staticvoidMain(){// 创建线程安全的ConcurrentBagvarbag=newConcurrentBag<int>();// 1. 多线程添加元素(4个线程,每个添加5个元素)Parallel.For(0,4,threadId=>{for(inti=1;i<=5;i++){intvalue=threadId*100+i;bag.Add(value);Console.WriteLine($"线程{threadId}:添加{value}");}});Console.WriteLine($"\n集合总元素数:{bag.Count}\n");// 2. 多线程消费元素(直到集合为空)Parallel.For(0,2,threadId=>{while(!bag.IsEmpty){if(bag.TryTake(outintvalue)){Console.WriteLine($"线程{threadId}:取出{value}");}// 避免空循环占用CPUTask.Delay(10).Wait();}});Console.WriteLine($"\n最终集合是否为空:{bag.IsEmpty}");}}

输出结果

线程0:添加 1 线程1:添加 101 线程0:添加 2 线程2:添加 201 ...(添加顺序无序) 集合总元素数:20 线程0:取出 2 线程1:取出 101 线程0:取出 1 线程1:取出 201 ...(取出顺序≠添加顺序,且优先取当前线程添加的元素) 最终集合是否为空:True

核心现象:

  • 添加和取出的顺序完全无序,符合ConcurrentBag<T>“无序集合” 的特性;

  • 同一线程优先取出自己添加的元素(TLS优化的体现)。

并行处理大量独立小文件
varfiles=Directory.GetFiles("big_folder","*.txt");varbag=newConcurrentBag<string>(files);Parallel.ForEach(bag,newParallelOptions{MaxDegreeOfParallelism=Environment.ProcessorCount},file=>{ProcessFile(file);});
对象池实现
publicclassObjectPool<T>{privatereadonlyConcurrentBag<T>_objects;privatereadonlyFunc<T>_objectGenerator;publicObjectPool(Func<T>objectGenerator){_objects=newConcurrentBag<T>();_objectGenerator=objectGenerator;}publicTGet(){return_objects.TryTake(outTitem)?item:_objectGenerator();}publicvoidReturn(Titem){_objects.Add(item);}}// 使用示例varpool=newObjectPool<StringBuilder>(()=>newStringBuilder());varsb=pool.Get();try{sb.Append("Hello");Console.WriteLine(sb.ToString());}finally{pool.Return(sb);}

关键特性与适用场景

核心特性
  • 顺序性: 无序(Add顺序≠遍历 /Take顺序)

  • 线程安全: 所有操作线程安全,无需手动加锁

  • 性能: 同线程存取:极高(无锁);跨线程窃取:中(轻量级锁)

  • 空值支持: 允许添加null(若T为引用类型)

  • 遍历特性: 遍历的是 “瞬时快照”,遍历过程中集合可修改,不抛出异常

  • 容量: 无固定容量限制,动态扩容

最佳适用场景
  • 线程自产自销:线程池线程添加元素后,自己快速取出处理(如线程本地缓存);

  • 无序批量处理:多线程收集数据,无需保证顺序(如日志收集、临时数据存储);

  • 低锁竞争场景:大多数操作由同一线程完成,跨线程操作少。

  • 对象池实现:重用对象减少分配

  • 并行计算中间结果收集

  • 生产者即消费者模式

不适用场景
  • 需要有序存取:如FIFO(用ConcurrentQueue<T>)、LIFO(用ConcurrentStack<T>);

  • 高跨线程窃取:多线程频繁添加,且其他线程频繁取走(此时锁竞争多,性能低于ConcurrentQueue<T>);

  • 索引访问:ConcurrentBag<T>无索引(如bag[0]),需索引访问用ConcurrentDictionary<TKey, TValue>或手动封装。

最佳实践

优先用于生产者-消费者同线程场景
// 同一线程添加和取出varthreadLocalBag=newConcurrentBag<WorkItem>();voidProcess(){threadLocalBag.Add(CreateWork());if(threadLocalBag.TryTake(outvarwork)){Execute(work);}}
避免用于生产者-消费者分离场景
// 生产者消费者分离varsharedBag=newConcurrentBag<Data>();// 生产者线程Task.Run(()=>sharedBag.Add(produce()));// 消费者线程Task.Run(()=>{if(sharedBag.TryTake(outvardata)){consume(data);}});

总结

ConcurrentBag<T>.NET并发集合中的特殊工具:

  • ✅ 在生产者即消费者场景中性能卓越

  • ✅ 内置工作窃取机制

  • ✅ 无锁实现减少竞争

  • ✅ 线程本地存储优化

最佳适用场景:

  • 线程处理自己生成的任务

  • 对象池实现

  • 并行计算的结果收集

  • 工作窃取模式的任务分发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1148091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI如何解决Vue.js未检测到的常见问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Vue.js项目检测工具&#xff0c;能够自动扫描项目目录&#xff0c;检查Vue.js是否正确安装和配置。工具应包含以下功能&#xff1a;1. 检查node_modules中Vue.js是否存在&…

学长亲荐10个AI论文写作软件,助你轻松搞定本科论文!

学长亲荐10个AI论文写作软件&#xff0c;助你轻松搞定本科论文&#xff01; 论文写作的“隐形助手”&#xff0c;你真的不需要它吗&#xff1f; 对于许多本科生来说&#xff0c;撰写一篇完整的论文是一项既复杂又耗时的任务。从选题、收集资料到撰写大纲、反复修改&#xff0c…

传统vs现代:AI如何让Chrome插件开发提速10倍

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个对比展示插件&#xff1a;左侧面板显示手动编写的传统插件代码(实现网页截图功能)&#xff0c;右侧面板展示AI生成的优化版本。要求包含&#xff1a;1)性能指标实时对比 2…

太牛批了,系统工具箱合集,免费实用

今天给大家推荐一款好用的系统工具箱&#xff0c;内含100多个工具&#xff0c;都可以免费使用&#xff0c;没有广告&#xff0c;有需要的小伙伴可以下载收藏。 盘姬工具箱 完全免费的电脑工具箱 软件下载后安装一下就可以使用了 &#xff0c;启动之后看到有很多功能可以供大家…

AI降本增效:如何用快马平台提升开发效率

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个基于React的个人博客网站&#xff0c;包含以下功能&#xff1a;1.响应式布局&#xff0c;适配手机和PC 2.文章列表展示 3.文章详情页 4.分类标签功能 5.暗黑模式切换。使用…

5个步骤搞定OpenWrt定制编译:从入门到精通的完整指南

5个步骤搞定OpenWrt定制编译&#xff1a;从入门到精通的完整指南 【免费下载链接】OpenWrt_x86-r2s-r4s-r5s-N1 一分钟在线定制编译 X86/64, NanoPi R2S R4S R5S R6S, 斐讯 Phicomm N1 K2P, 树莓派 Raspberry Pi, 香橙派 Orange Pi, 红米AX6, 小米AX3600, 小米AX9000, 红米AX6S…

快速掌握xmake:跨平台构建工具终极使用指南

快速掌握xmake&#xff1a;跨平台构建工具终极使用指南 【免费下载链接】xmake &#x1f525; 一个基于 Lua 的轻量级跨平台构建工具 项目地址: https://gitcode.com/xmake-io/xmake 项目核心价值 xmake是一款基于Lua脚本的轻量级跨平台构建工具&#xff0c;支持C/C、O…

CNPM快速原型开发:1小时搭建完整前端项目

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个前端项目快速生成器&#xff0c;功能&#xff1a;1. 支持主流框架(Vue/React/Angular)模板选择 2. 自动通过CNPM安装必要依赖 3. 集成常用工具链配置 4. 生成基础项目结构…

Qwen3-VL-8B-Instruct终极部署指南:从边缘设备到企业级应用的技术突破

Qwen3-VL-8B-Instruct终极部署指南&#xff1a;从边缘设备到企业级应用的技术突破 【免费下载链接】Qwen3-VL-8B-Instruct 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen3-VL-8B-Instruct 在AI技术快速迭代的今天&#xff0c;如何在有限硬件资源下部署强大的…

可视化文本智能分类|AI万能分类器WebUI使用全解

可视化文本智能分类&#xff5c;AI万能分类器WebUI使用全解“无需训练&#xff0c;即输即分”——基于StructBERT的零样本分类WebUI&#xff0c;让文本打标像填空一样简单。在舆情监控、工单处理、用户反馈分析等场景中&#xff0c;自动文本分类是提升效率的核心能力。传统方案…

Scene框架实战指南:5个步骤构建高性能Android单Activity应用

Scene框架实战指南&#xff1a;5个步骤构建高性能Android单Activity应用 【免费下载链接】scene Android Single Activity Applications framework without Fragment. 项目地址: https://gitcode.com/gh_mirrors/scene/scene Scene框架是字节跳动开源的轻量级Android导航…

零样本分类技术问答:关于AI万能分类器的20个常见问题

零样本分类技术问答&#xff1a;关于AI万能分类器的20个常见问题 1. 引言&#xff1a;什么是“AI万能分类器”&#xff1f; 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;文本分类是构建智能系统的基础能力之一。传统方法依赖大量标注数据进行模型训练&#xf…

AI如何帮你快速生成ASCII艺术与转换工具

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个ASCII码转换与生成工具&#xff0c;支持以下功能&#xff1a;1. 文本到ASCII码的实时转换 2. 图片转ASCII艺术画 3. 自定义ASCII字符集选择 4. 颜色和样式调整 5. 一键复制…

StructBERT零样本分类部署教程:医疗问诊分类

StructBERT零样本分类部署教程&#xff1a;医疗问诊分类 1. 引言 1.1 AI 万能分类器的时代来临 在当今信息爆炸的背景下&#xff0c;自动化文本分类已成为智能系统的核心能力之一。无论是客服工单、用户反馈还是医疗问诊记录&#xff0c;都需要快速准确地进行意图识别与归类…

新手必看:OPENSPEEDY官网入门指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个面向新手的OPENSPEEDY官网入门教程项目&#xff0c;包含从注册、创建项目、编写代码到部署上线的完整流程。教程以构建一个简单的个人博客网站为例&#xff0c;使用HTML、…

警惕!运输振动=医疗产品“隐形杀手”?ASTM D999标准强势护航

对于医疗器械、生物制药、疫苗、无菌敷料等企业而言&#xff0c;产品从生产车间到医院临床的运输环节&#xff0c;是保障产品质量的“最后一公里”。而运输途中不可避免的振动&#xff0c;堪称医疗产品的“隐形杀手”——精密医疗器械可能因振动偏离精度参数&#xff0c;冷链疫…

PCA在金融风控中的实际应用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个金融风控分析工具&#xff0c;使用PCA处理客户信用数据&#xff1a;1. 模拟生成包含20个特征的客户数据集&#xff1b;2. 应用PCA提取主要成分&#xff1b;3. 识别影响信用…

10分钟原型开发:用IndexedDB构建笔记应用MVP

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速开发一个基于IndexedDB的笔记应用原型&#xff0c;需要&#xff1a;1.支持富文本内容存储2.实现标签分类系统3.本地全文搜索功能4.数据导入/导出5.响应式UI。优先核心功能实现…

AI助力Docker部署Dify:智能代码生成实战

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成一个完整的Docker Compose配置文件&#xff0c;用于部署Dify AI平台。要求包含以下组件&#xff1a;1) Dify核心服务 2) PostgreSQL数据库 3) Redis缓存 4) 必要的环境变量配…

ResNet18茶叶品质鉴定:茶农的云端AI品茶师

ResNet18茶叶品质鉴定&#xff1a;茶农的云端AI品茶师 引言 想象一下&#xff0c;你是一位茶农&#xff0c;每天需要手工筛选数百斤茶叶&#xff0c;区分特级、一级、二级等不同品质。这项工作不仅耗时耗力&#xff0c;还容易因视觉疲劳导致判断偏差。现在&#xff0c;借助Re…