4

我正在使用 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 中的情况是相同的,因为在内存排序方面,两者共享相同的概念(甚至相同的枚举)。gccg++在这种情况下发出相同的机器代码。请参阅http://en.cppreference.com/w/c/atomic/memory_orderhttp://en.cppreference.com/w/cpp/atomic/memory_order

4

1 回答 1

5

store 之前的内存栅栏是为了保证 store 在之前的任何 store 之前都没有被订购。类似地,读取后的内存栅栏保证读取不会在任何后续读取之后排序。当您将两者结合起来时,它会在写入和读取之间创建一个同步关系。

T1: on-deps(A) -> fence -> write(A)

T2: read(A) -> fence -> deps-on(A)

read(A) 发生在 deps-on(A) 之前

write(A) 发生在 on-deps(A) 之后

如果你改变任何一个栅栏的顺序,依赖的顺序就会被破坏,这显然会导致不一致的结果(例如竞争条件)。

更多可能的阅读...

于 2015-10-23T07:23:53.223 回答