【发布时间】:2019-09-07 10:55:33
【问题描述】:
我试图理解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):
特别是执行释放操作的原子操作A 在对象 M 上与执行的原子操作 B 同步 对 M 的获取操作并读取由任何副作用写入的值 在以A为首的发布序列中。
因此,明确定义此代码行为的唯一方法是将atomic_exchange_explicit(&i, 200, memory_order_release) != 200 替换为atomic_exchange(&i, 200) != 200
【问题讨论】:
标签: c multithreading concurrency stdatomic