c++ - 在 C++11 中获取/释放 VS 顺序一致性?
问题描述
#include <thread>
#include <atomic>
#include <cassert>
std::atomic<bool> x = {false};
std::atomic<bool> y = {false};
std::atomic<int> z = {0};
void write_x()
{
x.store(true, std::memory_order_release);
}
void write_y()
{
y.store(true, std::memory_order_release);
}
void read_x_then_y()
{
while (!x.load(std::memory_order_acquire))
;
if (y.load(std::memory_order_acquire)) {
++z;
}
}
void read_y_then_x()
{
while (!y.load(std::memory_order_acquire))
;
if (x.load(std::memory_order_acquire)) {
++z;
}
}
int main()
{
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join(); b.join(); c.join(); d.join();
assert(z.load() != 0);
}
如果我在cppreference 的最后一个示例中将 seq_cst 替换为获取/释放,assert(z.load() != 0)
会失败吗?
- Seq_CST 可以防止 StoreLoad 重新排序,但代码没有。
- Acquire 可以防止 LoadLoad 重新排序。
- Release 可以防止 StoreStore 重新排序。
解决方案
是的,如果您使用/订购,则可能z.load() == 0
在您的代码中。独立写入和之间没有发生之前的关系。cppreference 使用该示例专门用于说明获取/释放不足的情况并非巧合。acquire
release
x
y
这有时被称为 IRIW(独立读取独立写入),并且在某些硬件排序模型中往往被掩盖。特别是,仅根据可能的加载加载、加载存储、存储存储等定义的内存模型,重新排序并没有真正说明 IRIW。在 x86 内存模型中,IRIW 重新排序是不允许的,因为有一个子句解释了存储具有总顺序并且所有处理器都以相同的顺序查看存储。
我不知道在使用获取和释放所需的障碍和/或指令时,是否有任何常用的 CPU 承认 IRIW 重新排序,但如果有人这样做,我不会感到惊讶。
推荐阅读
- reactjs - React JS 和 Google 电子表格:无法读取 Null 的属性“2”
- .net-core-3.1 - 为什么新的 .net core 控制台应用程序的 exe 文件这么大?
- security - 如何通过标签限制一组用户的 Jenkins 节点
- python - com.chaquo.python.PyException: ConnectionError: HTTPSConnectionPool(host='www.flipkart.com', port=443): url 超过了最大重试次数
- android - 应用关闭时,intent.action.PHONE_STATE 广播接收器不工作
- c++ - 即使将“g++”添加到系统路径变量中,也无法识别它
- javascript - 如何为反应组件创建唯一键
- sql - 有关列规范的 MS SQL Server Management Studio 的基本问题
- php - 如何使用 codeIgniter 获取关联值?
- javascript - 可以切换大小写将等待等待结果