atomic_exchange_explicit/atomic_exchange 引入的内存顺序

Memory order introduced by atomic_exchange_explicit/atomic_exchange

我试图理解 atomic_exchange[_explicit] 引起的内存排序并编写了以下代码:

static _Atomic int i = 123;

void *update(void *ignored){
    if(atomic_exchange_explicit(&i, 200, memory_order_release) != 200){ //1
        printf("Updated\n", stdout);
    } 
}

int main(int args, const char *argv[]){
    pthread_t t1;
    pthread_create(&t1, NULL, &update, NULL);

    pthread_t t2;
    pthread_create(&t2, NULL, &update, NULL);

    sleep(1000);
}

问题Updated\n 是否可能被打印两次(由两个线程)?

我认为行为未定义。即使我们在 //1 处将 memory_order_release 替换为 memory_order_acquire,UB 也会保留。生成的代码与 acq/rel/acq_rel 相同:https://godbolt.org/z/sFjcve .

这是因为我们有数据竞争,因为要保持同步关系,我们需要一个操作是 acquire 操作,下一个操作是 release 操作,释放操作读取一个由获取操作的释放序列的副作用写入的值 5.1.2.4(p11):

In particular, an atomic operation A that performs a release operation on an object M synchronizes with an atomic operation B that performs an acquire operation on M and reads a value written by any side effect in the release sequence headed by A.

因此,使此代码的行为明确定义的唯一方法是将 atomic_exchange_explicit(&i, 200, memory_order_release) != 200 替换为 atomic_exchange(&i, 200) != 200

你错了。无论请求的内存顺序如何,交换都是原子的。内存排序解释了这个读取、写入或读取-修改-写入操作如何与其他操作交互,但操作是 始终 原子的。