使用memory_order_release与memory_order_acquire配对可解决多线程共享变量可见性问题:A线程用release保证data写入在ready置true前完成并同步缓存,B线程用acquire确保读到ready后必能读到data最新值。

多线程程序中,一个线程修改了共享变量,另一个线程却始终读不到最新值——这不是编译器或CPU的“bug”,而是内存重排与缓存不一致共同导致的可见性陷阱;用 memory_order_release 配合 memory_order_acquire 可以在不加锁的前提下建立同步点,让写入对其他线程真正可见。
先复现可见性陷阱
定义两个全局原子变量:std::atomic<bool> ready{false}</bool> 和 std::atomic<int> data{0}</int>;线程A先写data = 42,再设ready = true;线程B循环等待ready == true后读data——但B可能永远读到0。
问题根源:编译器和CPU都可能把data = 42重排到ready = true之后执行,或者B读到ready为true时,data的新值还卡在A核心的私有缓存里没刷出。
用memory_order_release标记“发布点”
在线程A中,将ready.store(true, std::memory_order_release)代替默认的store。
立即学习“C++免费学习笔记(深入)”;
这一步强制要求:所有在store之前的内存操作(包括对data的写入)不能被重排到该store之后;同时触发缓存同步机制,使data = 42对其他核心可见——但仅限于能通过acquire语义观测到该release的线程。
【必须配对使用】 单独加release没有意义,它只对后续能建立synchronizes-with关系的acquire操作生效。
用memory_order_acquire建立获取点
在线程B中,将轮询改为while (!ready.load(std::memory_order_acquire)) { }。
这一步确保:一旦load返回true,所有在此load之后的内存操作(比如读data)不会被重排到该load之前;更重要的是,它能“看到”所有在对应release之前完成的写入——包括data = 42。
此时B读data.load()一定得到42,不再有可见性漏洞。
验证同步关系是否成立
第一步:确认两个原子操作作用于同一个变量——这里是ready。
第二步:检查A的store是否用memory_order_release(或更强),B的load是否用memory_order_acquire(或更强)。
第三步:确保B的load读到的值,是由A的store写入的——即存在happens-before链:A写ready → B读ready → B读data。
只要三步全满足,data的写就对B严格可见。其他组合如relaxed+acquire、release+relaxed均无法保证。


















