在理解原子变量之二:从volatile到内存序-进一步的认识-CSDN博客里的实例3里面,我们看到,如果在一个线程里修改原子变量done,另一个线程读取done时,就会看到这个变化。这就是原子变量的可见性。其实这个认识是不全面的。在std::memory_order - cppreference.com
里面这样描述 可见性:
最重要的是红线标出的这句话。它的意思是,假如如下两个条件同时满足:
1 a线程对某原子变量进行了写入操作,且使用了内存序memory_order_release,
2 b线程对同一个原子变量进行读操作,且使用了内存序memory_order_acquire
则b线程读取该原子变量后,不仅可以看到该原子变量的更新值(也就是a线程写入的值),还能看到a线程对该原子变量进行写入之前的所有其他的写操作的效果,不论是针对该原子变量的,还是针对其他变量的,也不论这些变量是不是原子变量,也不论使用何种内存序。
看下面示例(来自std::memory_order - cppreference.com)
#include <atomic>
#include <cassert>
#include <string>
#include <thread>
std::atomic<std::string*> ptr;
int data;
void producer()
{
std::string* p = new std::string("Hello");
data = 42;//a线程写入原子变量前的写操作,data只是一个普通变量
ptr.store(p, std::memory_order_release);//线程写入原子变量
}
void consumer()
{
std::string* p2;
while (!(p2 = ptr.load(std::memory_order_acquire)))//b线程读取原子变量
;
assert(*p2 == "Hello"); // 绝无问题
assert(data == 42); // 绝无问题,
//因为data=42这句话,发生在a线程写入原子变量之前,
//所以在b线程读取原子变量后,data的更新值对b线程是可见的
}
int main()
{
std::thread t1(producer);//这就是线程a
std::thread t2(consumer);//这就是线程b
t1.join();
t2.join();
}
尽管data是一个普通变量,但是data=42这个操作发生在ptr.store之前(且采用内存序release),所以consumer函数读取ptr.load之后(且采用内存序acquire),也可以看到data的最新值42
但是注意,假如还有第三个线程,且第三个线程不操作原子变量ptr,或者虽然操作ptr,但是使用比较弱的内存序,如前一篇所说的relaxed,则release之前发生的写入操作的效果,不一定能像使用acquire那样被第三个线程观察到。
标签:std,变量,acquire,原子,线程,memory,data,order From: https://blog.csdn.net/liji_digital/article/details/143996082