c++ - C++ 这个 MPMC 队列中的原子需要什么内存顺序?
问题描述
这是我仅使用原子实现的无锁、无等待、多线程安全的 MPMC 队列:
template <typename T, int32_t SIZE>
class queue_mpmc {
T ar[SIZE];
std::atomic_uint64_t start;
std::atomic_uint64_t end;
std::atomic_int32_t precount;
std::atomic_int32_t postcount;
public:
queue_mpmc() {
start = 0;
end = 0;
precount = 0;
postcount = 0;
}
bool trypush(T data) {
int32_t c = ++precount; // this must be done before the line beginning ar
if (c > SIZE) { [[unlikely]]
--precount;
return false;
}
ar[end++ % SIZE] = data;
++postcount; // this must be done after the line beginning ar
return true;
}
T trypop() {
int32_t c = --postcount; // this must be done before the line beginning ar
if (c < 0) {
++postcount;
return T{};
}
T r = ar[start++ % SIZE];
--precount; // this must be done after the line beginning ar
return r;
}
int32_t len() {
return precount;
}
};
它被设计为 SIZE 的 2 倍(32、64、128、256 等),因为在这些情况下,由于编译器优化,它使用模运算符提供了对底层数组的有效环绕。
我一直在阅读有关 atomic memory order的内容,但我对此并不陌生,我无法弄清楚这是否适用于我正在使用的 atomics?该设计确实依赖于++/--precount
and在and指令++/--postcount
之前或之后(位于开头的行内)。就是这样,并且只需要应用于当前线程,它不需要在线程之间同步超出通常预期的原子。end++
start++
ar
我可以通过指定内存顺序来提高性能吗?
解决方案
如果其他错误已修复,则很可能 start
,end
和precount
在所有用途中都可以是 memory_order_relaxed 。
postcount
是表示一个值已写入队列的变量。即它控制值的发布和值的读取。
所以postcount
在推送中需要memory_order_release(“发布”),在读取之前需要memory_order_acquire(即在pop中)。
也许。
推荐阅读
- python - 如何在python中以长度= 32字节的序列将整数转换为二进制数
- java - Spring boot:未在测试类中设置属性值
- android - 片段中带有 Spinner 的“setAdapter”不起作用
- android - 找不到 com.android.support:appcompat-v7:27.1.1 | 反应本机矢量图标
- flatpickr - 如何更改 flatpickr 默认时区
- java - 从字符串的开头删除所有或某些特殊字符
- swift - 从 Xcode 调用 C 库函数
- sails.js - 通过模型设置创建唯一的多键索引
- javascript - 如何在 testcafe 中调用外部异步等待函数
- javascript - url-createobjecturl-no-longer-accepts-mediastream - 在 2018 年 12 月 14 日 Chrome 更新之后