ConcurrentQueue无法替代环形缓冲区,因其链表实现导致内存不连续、缺乏原子批次操作、不支持预分配与零拷贝;环形缓冲区在SPSC场景下凭借固定容量、缓存友好和无锁特性,更适用于高吞吐低延迟场景。
ConcurrentQueue 代替环形缓冲区因为 ConcurrentQueue 是链表实现,内存不连续,无法保证写入/读取的原子性批次,也不支持预分配固定大小和零拷贝访问。环形缓冲区核心价值在于:确定容量、缓存友好、单生产者/单消费者(SPSC)场景下免锁、支持指针快速读写。如果你需要的是高吞吐低延迟的日志暂存、网络包收发或实时音频流缓冲,ConcurrentQueue 的 GC 压力和间接寻址开销会成为瓶颈。
Interlocked 实现 SPSC 无锁环形缓冲区关键不是“完全不用锁”,而是避免 lock 语句阻塞线程;SPSC 场景下,仅用 Interlocked.CompareExchange 和 Interlocked.Add 即可协调读写索引。必须满足:一个线程只写、一个线程只读,且不允许多对一或一对多。
T[] 预分配,长度为 2 的幂(便于位运算取模)_writeIndex)和读索引(_readIndex)均为 long 类型,避免 32 位溢出导致误判index & (_capacity - 1) 计算,比 % _capacity 快且安全Interlocked.CompareExchange 检查是否有足够空位,失败则返回 false(不阻塞)Interlocked.Add 批量推进读索引public sealed class RingBuffer{ private readonly T[] _buffer; private readonly int _capacity; private readonly int _mask; private long _writeIndex; private long _readIndex; public RingBuffer(int capacity) { _capacity = RoundUpToPowerOfTwo(capacity); _mask = _capacity - 1; _buffer = new T[_capacity]; } public bool TryWrite(T item) { long writePos = Interlocked.Read(ref _writeIndex); long readPos = Interlocked.Read(ref _readIndex); long available = _capacity - (writePos - readPos); if (available zuojiankuohaophpcn= 0) return false; _buffer[writePos & _mask] = item; Interlocked.Increment(ref _writeIndex); return true; } public bool TryRead(out T item) { item = default!; long writePos = Interlocked.Read(ref _writeIndex); long readPos = Interlocked.Read(ref _readIndex); if (writePos == readPos) return false; item = _buffer[readPos & _mask]; Interlocked.Increment(ref _readIndex); return true; } private static int RoundUpToPowerOfTwo(int v) { v--; v |= v youjiankuohaophpcnyoujiankuohaophpcn 1; v |= v youjiankuohaophpcnyoujiankuohaophpcn 2; v |= v youjiankuohaophpcnyoujiankuohaophpcn 4; v |= v youjiankuohaophpcnyoujiankuohaophpcn 8; v |= v youjiankuohaophpcnyoujiankuohaophpcn 16; return v + 1; }}
为什么
volatile不够,而必须用Interlocked.Read在 x86/x64 上,
volatile字段读写会插入内存屏障,但不能保证“读-改-写”操作的原子性。比如两个线程同时执行
_writeIndex++,即使字段是volatile,仍可能丢失一次自增。而Interlocked.Read(ref _writeIndex)不仅保证读取最新值,还强制刷新 CPU 缓存行,确保你看到的是其他线程写入后的结果。尤其在 ARM 平台上,缺少Interlocked会导致读写索引严重错乱。容易被忽略的边界:批量读写与内存可见性
上面示例是单元素读写,实际中常需
TryWriteBatch或TryReadBatch。这时不能简单循环调用TryWrite,否则每轮都重复检查可用空间,效率低且逻辑错乱。正确做法是:一次计算最大可写数量,用Interlocked.CompareExchange原子预留位置,再逐个赋值,最后用Interlocked.Add提交写索引偏移。同样,读端也要先确认数据量,再批量复制,最后提交读索引——否则中间被写端覆盖就丢数据了。另外,如果
T是引用类型,写入时只是存引用,不触发对象复制;但若T是结构体且较大(如超过 16 字节),要考虑缓存行对齐和复制开销。无锁结构体写入本身没问题,但频繁大结构体搬运会抵消无锁带来的性能优势。
# 字节 # ai # c# # 无锁 # 为什么 # 结构体 # volatile # 循环 # 指针 # 引用类型 # 线程 # 对象 # 的是 # 链表 # 不连续 # 如果你 # 也不 # 均为 # 适用于 # 不支持 # 要先 # 再用
相关文章: 如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本 香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南 制作国外网站的软件,国外有哪些比较优质的网站推荐? 建站主机数据库如何配置才能提升网站性能? 建站之星下载版如何获取与安装? 红河网站制作公司,红河事业单位身份证如何上传? ,交易猫的商品怎么发布到网站上去? 微网站制作教程,我微信里的网站怎么才能复制到浏览器里? 建站168自助建站系统:快速模板定制与SEO优化指南 如何用搬瓦工VPS快速搭建个人网站? css网站制作参考文献有哪些,易聊怎么注册? javascript基本数据类型及类型检测常用方法小结 如何快速选择适合个人网站的云服务器配置? 黑客如何利用漏洞与弱口令入侵网站服务器? 香港服务器WordPress建站指南:SEO优化与高效部署策略 外贸公司网站制作哪家好,maersk船公司官网? 建站之星如何快速生成多端适配网站? 详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七) 东莞专业制作网站的公司,东莞大学生网的网址是什么? 建站之星多图banner生成与模板自定义指南 建站之星如何快速解决建站难题? 如何用花生壳三步快速搭建专属网站? 如何选择最佳自助建站系统?快速指南解析优劣 大连企业网站制作公司,大连2025企业社保缴费网上缴费流程? 网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站? TestNG的testng.xml配置文件怎么写 大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊? 如何获取开源自助建站系统免费下载链接? php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】 网站制作哪家好,cc、.co、.cm哪个域名更适合做网站? 广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网? 个人摄影网站制作流程,摄影爱好者都去什么网站? ,南京靠谱的征婚网站? 香港服务器部署网站为何提示未备案? 如何在Golang中引入测试模块_Golang测试包导入与使用实践 如何使用Golang table-driven基准测试_多组数据测量函数效率 如何安全更换建站之星模板并保留数据? 宝塔建站无法访问?如何排查配置与端口问题? 浅析上传头像示例及其注意事项 如何挑选最适合建站的高性能VPS主机? 如何将凡科建站内容保存为本地文件? C#如何序列化对象为XML XmlSerializer用法 网站好制作吗知乎,网站开发好学吗?有什么技巧? 手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站? 商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计? 整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去? ,购物网站怎么盈利呢? 想学网站制作怎么学,建立一个网站要花费多少? 模具网站制作流程,如何找模具客户? 公司网站制作需要多少钱,找人做公司网站需要多少钱?
*请认真填写需求信息,我们会在24小时内与您取得联系。