为何不同线程可观测不同内存操作顺序?C++并发原子操作疑问
C++原子操作内存序疑惑解答
问题背景
以下是《C++ Concurrency in Action(第二版)》中的示例代码,作者指出线程Tc和Td可能观测到不同的内存状态:
- Tc观测到
x == true且y == false - Td观测到
x == false且y == true
最终z的值可能为0,触发断言失败。
示例代码
std::atomic<bool> x(false), y(false); std::atomic<int> z(0); void write_x() { // Ta x.store(true, std::memory_order_release); // A } void write_y() { // Tb y.store(true, std::memory_order_release); // B } void read_x_then_y() { // Tc while(!x.load(std::memory_order_acquire)); // C if(y.load(std::memory_order_acquire)) // D ++z; } void read_y_then_x() { // Td while(!y.load(std::memory_order_acquire)); // E if(x.load(std::memory_order_acquire)) // F ++z; } int main() { std::thread a(write_x); std::thread b(write_y); std::thread c(read_x_then_y); std::thread d(read_y_then_x); a.join(); b.join(); c.join(); d.join(); assert(z.load() != 0); }
你最初的理解是:语句A和B的执行顺序要么是AB要么是BA,假设为AB时,Td看到y=true后必然能看到x=true,所以z一定会大于0,但这个理解存在错误。
错误点解析
1. 错误假设了"全局执行顺序"
C++内存模型中不存在全局统一的操作执行顺序,只有线程内部的程序顺序和线程间的同步关系。Ta和Tb是完全独立的线程,它们的store操作之间没有任何同步约束,不存在全局意义上的AB或BA执行顺序。
2. 误解了release-acquire同步的作用范围
std::memory_order_release和std::memory_order_acquire仅能在特定的线程对之间建立同步关系:
- Ta的
x.store(..., release)和Tc的x.load(..., acquire)同步:Tc看到x=true时,能保证看到Ta中所有在该store之前的操作,但这和Tb的操作毫无关联。 - Tb的
y.store(..., release)和Td的y.load(..., acquire)同步:Td看到y=true时,能保证看到Tb中所有在该store之前的操作,但和Ta的操作无关。
Ta和Tb之间没有任何同步机制,所以它们的操作在其他线程的内存视图中可能是乱序的。
3. 导致z=0的具体场景
- Tc通过while循环看到x=true(确认Ta的store已对自己可见),但此时Tb的y.store操作可能还未对Tc可见,所以Tc执行D时y=false,不会执行
++z。 - Td通过while循环看到y=true(确认Tb的store已对自己可见),但此时Ta的x.store操作可能还未对Td可见,所以Td执行F时x=false,也不会执行
++z。 - 最终z的值为0,触发断言失败。
你之前的错误在于认为"如果A在全局先于B,那么Td看到y=true时必然看到x=true",但全局顺序并不存在,Td看到y=true仅和Tb的操作同步,无法推导出Ta的操作对其可见。
内容的提问来源于stack exchange,提问作者hao
相关产品推荐
相关产品推荐

