标准中是否有任何措辞保证不会将宽松的原子存储提升到互斥锁的锁定之上?如果没有,是否有任何措辞明确表示编译器或 CPU 这样做是符合犹太教规的?
例如,使用下面的程序(它可能使用 acq/rel 来foo_has_been_set
避免锁,和/或使foo
自己成为原子的。这样写是为了说明这个问题。)
std::mutex mu;
int foo = 0; // Guarded by mu
std::atomic<bool> foo_has_been_set{false};
void SetFoo() {
mu.lock();
foo = 1;
foo_has_been_set.store(true, std::memory_order_relaxed);
mu.unlock();
}
void CheckFoo() {
if (foo_has_been_set.load(std::memory_order_relaxed)) {
mu.lock();
assert(foo == 1);
mu.unlock();
}
}
如果另一个线程同时调用,是否有可能CheckFoo
在上述程序中崩溃SetFoo
,或者是否有一些保证不能将存储提升到编译器和 CPUfoo_has_been_set
的调用之上?mu.lock
这与一个较旧的问题有关,但我并不是 100% 清楚那里的答案适用于此。特别是,该问题答案中的反例可能适用于对 的两个并发调用SetFoo
,但我对编译器知道有一个调用SetFoo
和一个调用的情况感兴趣CheckFoo
。能保证安全吗?
我正在寻找标准中的特定引用。