这里的顺序一致性有什么问题?
What's wrong with sequental consistency here?
我正在研究 C 和 C++ 中的无锁算法,最近偶然发现了一个我不太理解的行为。如果你有下面的代码,运行 它会给你类似
reader started
writer started
iters=79895047, less=401131, eq=48996928, more=30496988
难道 std::atomics
不应该是顺序一致的吗?如果是这样,为什么 reader 有时会看到 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++;
}
}
顺序一致的内存排序意味着所有线程观察到的(用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
,您可以确保操作不会交错。
我正在研究 C 和 C++ 中的无锁算法,最近偶然发现了一个我不太理解的行为。如果你有下面的代码,运行 它会给你类似
reader started writer started iters=79895047, less=401131, eq=48996928, more=30496988
难道 std::atomics
不应该是顺序一致的吗?如果是这样,为什么 reader 有时会看到 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++;
}
}
顺序一致的内存排序意味着所有线程观察到的(用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
,您可以确保操作不会交错。