我在C和C ++中使用无锁算法,最近偶然发现了一个我不太了解的行为。如果您有以下代码,运行它将为您提供类似
的内容reader started writer started iters=79895047, less=401131, eq=48996928, more=30496988
Aren&#t; t std::atomics
预计会按顺序保持一致吗?如果是这样,为什么读者有时会在b
之前看到a
被更新?我还试图做各种涉及内存栅栏的技巧但没有成功。完整的可编辑代码可以在https://github.com/akamaus/fence_test
这个例子有什么问题?
std::atomic<uint> a(0);
std::atomic<uint> b(0);
volatile bool stop = false;
void *reader(void *p) {
uint64_t iter_counter = 0;
uint cnt_less = 0,
cnt_eq = 0,
cnt_more = 0;
uint aa, bb;
printf("reader started\n");
while(!stop) {
iter_counter++;
aa = a.load(std::memory_order_seq_cst);
bb = b.load(std::memory_order_seq_cst);
if (aa < bb) {
cnt_less++;
} else if (aa > bb) {
cnt_more++;
} else {
cnt_eq++;
}
}
printf("iters=%lu, less=%u, eq=%u, more=%u\n", iter_counter, cnt_less, cnt_eq, cnt_more);
return NULL;
}
void *writer(void *p) {
printf("writer started\n");
uint counter = 0;
while(!stop) {
a.store(counter, std::memory_order_seq_cst);
b.store(counter, std::memory_order_seq_cst);
counter++;
}
}
答案 0 :(得分:4)
顺序一致的内存排序意味着所有线程观察到的(使用seq cst操纵的原子对象的)修改顺序是一致的。该程序的行为就好像所有这些操作在一个总顺序中交错进行。请考虑以下情况:
Writer Reader a == 0 a = 1 b = 1 b == 1
结果:aa < bb
。
Writer Reader a = 1 a == 1 b == 0 b = 1
结果:aa > bb
带锁,例如a mutex
,您可以确保操作不会交错。