我正在使用C11 * atomics来管理几个线程之间的状态枚举。该代码类似于以下内容:
static _Atomic State state;
void setToFoo(void)
{
atomic_store_explicit(&state, STATE_FOO, memory_order_release);
}
bool stateIsBar(void)
{
return atomic_load_explicit(&state, memory_order_acquire) == STATE_BAR;
}
将(对于ARM Cortex-M4)组装为:
<setToFoo>:
ldr r3, [pc, #8]
dmb sy ; Memory barrier
movs r2, #0
strb r2, [r3, #0] ; store STATE_FOO
bx lr
.word 0x00000000
<stateIsBar>:
ldr r3, [pc, #16]
ldrb r0, [r3, #0] ; load state
dmb sy ; Memory barrier
sub.w r0, r0, #2 ; Comparison and return follows
clz r0, r0
lsrs r0, r0, #5
bx lr
.word 0x00000000
为什么围栏在发布之前放置 之后获取?我的心智模型假设在发布之后(将“存储的变量”和所有其他商店“传播”到其他线程)和之前获取后放置屏障(从其他线程接收所有以前的商店。)
*虽然这个特定的例子在C11中给出,但在C ++ 11中的情况是相同的,因为在内存排序方面,两者共享相同的概念(甚至是相同的枚举)。在这种情况下,gcc
和g++
会发出相同的机器代码。请参阅http://en.cppreference.com/w/c/atomic/memory_order和http://en.cppreference.com/w/cpp/atomic/memory_order
答案 0 :(得分:5)
商店之前的内存栅栏是为了保证在任何先前商店之前没有订购商店。类似地,读取后的内存栅栏保证在任何后续读取后不读取读取。将两者结合使用时,它会在写入和读取之间创建同步 - 关系。
T1: on-deps(A) -> fence -> write(A)
T2: read(A) -> fence -> deps-on(A)
读取(A)发生在deps-on(A)
之前写(A)发生在on-deps(A)
之后如果更改任一栅栏的顺序,则依赖序列会被破坏,这显然会导致不一致的结果(例如竞争条件)。
更多可能的阅读...