全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

c# 如何在C#中实现一个无锁环形缓冲区(Ring Buffer)

ConcurrentQueue无法替代环形缓冲区,因其链表实现导致内存不连续、缺乏原子批次操作、不支持预分配与零拷贝;环形缓冲区在SPSC场景下凭借固定容量、缓存友好和无锁特性,更适用于高吞吐低延迟场景。

为什么不能直接用 ConcurrentQueue 代替环形缓冲区

因为 ConcurrentQueue 是链表实现,内存不连续,无法保证写入/读取的原子性批次,也不支持预分配固定大小和零拷贝访问。环形缓冲区核心价值在于:确定容量、缓存友好、单生产者/单消费者(SPSC)场景下免锁、支持指针快速读写。如果你需要的是高吞吐低延迟的日志暂存、网络包收发或实时音频流缓冲,ConcurrentQueue 的 GC 压力和间接寻址开销会成为瓶颈。

如何用 Interlocked 实现 SPSC 无锁环形缓冲区

关键不是“完全不用锁”,而是避免 lock 语句阻塞线程;SPSC 场景下,仅用 Interlocked.CompareExchangeInterlocked.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 会导致读写索引严重错乱。

容易被忽略的边界:批量读写与内存可见性

上面示例是单元素读写,实际中常需 TryWriteBatchTryReadBatch。这时不能简单循环调用 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小时内与您取得联系。