由atomic_exchange_explicit / atomic_exchange引入的内存顺序

时间:2019-04-17 08:41:49

标签: c multithreading concurrency stdatomic

我试图了解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是否有可能被打印两次(通过两个线程)?

我认为行为是不确定的。即使我们将memory_order_release的{​​{1}}替换为memory_order_acquire,也将保留UB。生成的代码与acq / rel / acq_rel相同:https://godbolt.org/z/sFjcve

这是因为我们要进行数据竞争,因为要与关系保持同步,我们需要一个操作是//1操作,而下一个操作是acquire操作,释放操作读取一个写入的值由获取操作release的释放序列引起的副作用:

  

尤其是执行释放操作的原子操作A   对对象M的同步与执行的原子操作B同步   对M的获取操作,并读取任何副作用写入的值   以A为首的释放顺序。

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

1 个答案:

答案 0 :(得分:4)

您不正确。无论请求的内存顺序如何,交换都是原子的。内存顺序说明了此读取,写入或读取-修改-写入操作如何与其他操作交互,但是该操作始终是 原子。