[英]Acquire/Release VS Sequential Consistency in C++11?
#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);
}
If I relplace seq_cst to acquire/release in cppreference's last example , can assert(z.load() != 0)
be fail ?如果我在cppreference 的最后一个示例中将 seq_cst 替换为获取/释放,
assert(z.load() != 0)
会失败吗?
Yes, it is possible that z.load() == 0
in your code if you use acquire
/ release
order as you've done.是的,如果您像您一样使用
acquire
/ release
顺序,则您的代码中可能会出现z.load() == 0
。 There is no happens-before relationship between the independent writes to x
and y
.对
x
和y
的独立写入之间没有发生之前的关系。 It's not a coincidence cppreference used that example specifically to illustrate a case where acquire/release isn't sufficient. cppreference 专门使用该示例来说明获取/释放不足的情况并非巧合。
This is sometimes call the IRIW (independent reads of independent writes), and tended to be glossed over in some hardware ordering models.这有时被称为 IRIW(独立写入的独立读取),并且在某些硬件订购模型中往往被掩盖。 In particular, a memory model defined only in terms of the possible load-load, load-store, store-store, etc, reorderings doens't say anything either way really about IRIW.
特别是,仅根据可能的加载-加载、加载-存储、存储-存储等定义的内存模型,重新排序并没有真正说明 IRIW。 In the x86 memory model IRIW reordering is disallowed because of a clause that explains that stores have a total order and all processors view stores in this same order.
在 x86 内存模型中,IRIW 重新排序是不允许的,因为有一个条款解释了存储具有总顺序并且所有处理器都以相同的顺序查看存储。
I'm not aware if any CPUs in common use admit the IRIW reordering when the barriers and/or instructions needed for acquire and release are used, but I wouldn't be surprised if some do.我不知道当使用获取和释放所需的障碍和/或指令时,是否有任何常用的 CPU 承认 IRIW 重新排序,但如果有人这样做,我不会感到惊讶。
Yes, the assert can fire.是的,断言可以触发。
The principal property that is not guaranteed by acquire / release is a single total order of modifications.不由获取/释放保证的主要属性是修改的单个总顺序。 It only guarantees that (the non-existent) previous actions of
a
and b
are observed by c
and d
if they see true
from the loads.它仅保证
a
和b
(不存在的)先前动作被c
和d
观察到,如果它们从负载中看到是true
。
A (slightly contrived) example of this is on a multi-cpu (physical socket) system that isn't fully cache-coherant.一个(稍微人为的)示例是在不完全缓存一致的多 CPU(物理套接字)系统上。 Die 1 has core A running thread
a
and core C running thread c
. Die 1 具有运行线程
a
内核 A 和运行线程c
内核 C 。 Die 2 has core B running thread b
and core D running thread d
. Die 2 具有运行线程
b
内核 B 和运行线程d
内核 D 。 The interconnect between the two sockets has a long latency when compared to a memory operation that hits on-die cache.与命中片上缓存的内存操作相比,两个插槽之间的互连具有较长的延迟。
a
and b
run at the same wall clock time. a
和b
在相同的挂钟时间运行。 C is on-die with A, so can see the store to x
immediately, but the interconnect delays it's observation of the store to y
, so it sees the old value. C 与 A 一起在芯片上,因此可以立即看到
x
的存储,但互连将其对存储的观察延迟到y
,因此它看到旧值。 Similarly D is on-die with B, so it sees the store to y
, but misses the store to x
.类似地,D 与 B 处于死机状态,因此它看到了
y
的存储,但错过了x
的存储。
Whereas if you have sequential consistency, some co-ordination is required to enforce a total order, such as "C and D are blocked while the interconnect syncs the caches".而如果您具有顺序一致性,则需要一些协调来强制执行总顺序,例如“互连同步缓存时 C 和 D 被阻塞”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.