我试图了解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
答案 0 :(得分:4)
您不正确。无论请求的内存顺序如何,交换都是原子的。内存顺序说明了此读取,写入或读取-修改-写入操作如何与其他操作交互,但是该操作始终是 原子。