新闻中心
c++如何实现一个环形缓冲区(Ring Buffer)_c++高性能无锁数据结构
答案:基于原子操作实现单生产者单消费者无锁环形缓冲区,利用std::atomic与内存序保证线程安全,通过模运算管理固定大小缓冲区的读写索引,适用于高吞吐低延迟场景。

环形缓冲区(Ring Buffer),也叫循环队列,是一种高效的固定大小缓冲区,常用于生产者-消费者场景。在C++中实现高性能、无锁的环形缓冲区,关键在于利用原子操作避免加锁,提升并发性能。下面介绍一个线程安全、无锁的单生产者单消费者(SPSC)环形缓冲区实现方式。
基本原理与设计要点
环形缓冲区使用一块连续内存,通过两个指针(或索引)管理数据:
- 写索引(write index):指向下一个可写入的位置
- 读索引(read index):指向下一个可读取的位置
当索引到达末尾时,自动回到开头,形成“环形”。为了实现无锁,读写索引使用std::atomic类型,并限制为单生产者单消费者模型,这样可以避免复杂的同步问题。
无锁SPSC Ring Buffer 实现
以下是一个简洁高效的实现示例:
GoEnhance
全能AI视频制作平台:通过GoEnhance AI让视频创作变得比以往任何时候都更简单。
347
查看详情
#include <atomic>
#include <vector>
<p>template <typename T>
class RingBuffer {
private:
std::vector
<T> buffer;
std::atomic<size_t> read_index{0};
std::atomic<size_t> write_index{0};
const size_t capacity;</p><p>public:
explicit RingBuffer(size_t size) : buffer(size), capacity(size) {}</p><pre class="brush:php;toolbar:false;">bool push(const T& item) {
size_t current_write = write_index.load(std::memory_order_relaxed);
size_t next_write = (current_write + 1) % capacity;
if (next_write == read_index.load(std::memory_order_acquire)) {
return false; // 缓冲区满
}
buffer[current_write] = item;
write_index.store(next_write, std::memory_order_release);
return true;
}
bool pop(T& item) {
size_t current_read = read_index.load(std::memory_order_relaxed);
if (current_read == write_index.load(std::memory_order_acquire)) {
return false; // 缓冲区空
}
item = buffer[current_read];
size_t next_read = (current_read + 1) % capacity;
read_index.store(next_read, std::memory_order_release);
return true;
}
bool empty() const {
return read_index.load() == write_index.load();
}
bool full() const {
size_t next_write = (write_index.load() + 1) % capacity;
return next_write == read_index.load();
}};
关键细节说明
这个实现的关键点包括:
- 内存序选择:load(std::memory_order_acquire) 和 store(std::memory_order_release) 配对使用,确保内存可见性,同时保持高性能
- 模运算优化:若容量为2的幂,可用位运算 (index + 1) & (capacity - 1) 替代%,提升速度
- SPSC安全前提:仅允许一个线程写,一个线程读,否则原子操作不足以保证正确性
- 不支持动态扩容:固定大小是无锁实现的基础
使用示例
简单用法如下:
RingBuffer<int> rb(8);
rb.push(42);
int val;
if (rb.pop(val)) {
// val == 42
}
基本上就这些。这个实现轻量、高效,适合高吞吐低延迟场景,比如音视频处理、日志系统、网络包缓存等。只要满足单生产者单消费者模型,就能发挥最大性能。多生产者或多消费者场景需更复杂的设计,通常建议使用其他并发队列如moodycamel::BlockingConcurrentQueue。
以上就是c++++如何实现一个环形缓冲区(Ring Buffer)_c++高性能无锁数据结构的详细内容,更多请关注其它相关文章!
# 就能
# 网站建设怎么发新闻
# 上海产品推广营销
# 河南seo线上营销怎么引流
# 顺义网站建设优化
# 思茅网站建设服务
# 电商营销推广案例分析
# 淄博seo优化前景
# 酒店网站建设怎样
# 抖音营销推广系统招商加盟
# 个人网站建设银行工作
# c++
# 是一种
# 迭代
# 是一个
# 解决方法
# 重写
# 如何实现
# 有什么
# 高性能
# 数据结构
# 无锁
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
利用Bokeh CustomJS动态控制DataTable列可见性
Python:递归比较文件夹内容并找出特定类型文件的差异
顺丰快递查询系统 官方正版查询入口
Win11如何开启讲述人功能 Win11屏幕阅读器(讲述人)开启与关闭【教程】
蛙漫官方正版入口 蛙漫网页在线全集免费观看
荣耀Play7T运行卡顿解决_荣耀Play7T性能优化
word中如何让数字纵向排列_Word数字纵向排列方法
照顾宝贝2小游戏点击立即在线玩
PySpark中高效提取字符串右侧可变长度数字:使用regexp_extract
J*aScript中管理异步API调用:确保操作顺序与数据一致性
在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用
Go语言中Map存储的结构体如何调用指针方法:深入解析与实践
深入理解Google Cloud Datastore查询:祖先路径与数据一致性
动漫岛观看全网网 动漫岛在线正版动漫入口
c++ dfs和bfs代码 c++深度广度优先搜索算法
C#使用XPath查询节点时出错? 常见语法错误与调试技巧
荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】
J*aScript中向JSON对象添加新属性的正确姿势
PS5 Pro有点优势但不多! 《燕云十六声》PS5平台与PC性能画面对比
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
Sublime怎么配置Nim语言环境_Sublime Nim代码高亮与补全
在J*a中如何捕获IndexOutOfBoundsException_索引越界异常防护方法说明
Yandex官网免登录入口_俄罗斯Yandex搜索引擎一键访问
机器学习中对数变换预测结果的反向还原
Python模块化编程:有效管理依赖与避免循环引用
CSS响应式网页如何实现主次模块比例自适应_flex-grow与flex-shrink调整
Windows7怎么硬盘安装 Windows7提取ISO镜像到非系统盘并运行setup.exe实现硬盘直装【教程】
J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案
消息称三星明年 2 月正式发布 HBM4,与 SK 海力士同台竞技
JUnit5/Mockito:优雅测试内部依赖与异常处理的实践
晋江读书网页版在线登录 晋江读书电脑版官网
如何为你的Composer包编写自动化测试_集成PHPUnit到Composer的scripts工作流
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
抖音网页版怎么|直播|_抖音网页版开播操作指南
深入理解Go语言中Map值与方法接收器的交互:为什么需要临时变量
AO3官网镜像链接 Archive of Our Own同人文在线浏览
微信群消息显示延迟如何解决 微信群消息刷新优化方法
b站怎么看视频的弹幕数量_b站弹幕数量查看方法
J*aScript对象创建方式_J*aScript设计模式应用
TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法
React/Next.js中实现列表项的动态选择与移动
极兔快递快件信息查询系统 极兔快递官网运单号追踪
sublime怎么设置启动时打开的窗口_sublime会话管理与热退出
在J*a中如何隐藏复杂性_使用门面模式组织对象交互
Win10如何开启蓝牙功能_Windows10找不到蓝牙开关解决方法
护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?
铁路12306的积分有效期是多久_铁路12306积分有效期说明
win11 Snap Layouts怎么用 Win11窗口布局与分屏多任务高效指南【必学】
现代化 SciPy 一维插值:interp1d 的替代方案与最佳实践


2025-11-30
浏览次数:次
返回列表
<T> buffer;
std::atomic<size_t> read_index{0};
std::atomic<size_t> write_index{0};
const size_t capacity;</p><p>public:
explicit RingBuffer(size_t size) : buffer(size), capacity(size) {}</p><pre class="brush:php;toolbar:false;">bool push(const T& item) {
size_t current_write = write_index.load(std::memory_order_relaxed);
size_t next_write = (current_write + 1) % capacity;
if (next_write == read_index.load(std::memory_order_acquire)) {
return false; // 缓冲区满
}
buffer[current_write] = item;
write_index.store(next_write, std::memory_order_release);
return true;
}
bool pop(T& item) {
size_t current_read = read_index.load(std::memory_order_relaxed);
if (current_read == write_index.load(std::memory_order_acquire)) {
return false; // 缓冲区空
}
item = buffer[current_read];
size_t next_read = (current_read + 1) % capacity;
read_index.store(next_read, std::memory_order_release);
return true;
}
bool empty() const {
return read_index.load() == write_index.load();
}
bool full() const {
size_t next_write = (write_index.load() + 1) % capacity;
return next_write == read_index.load();
}