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