网站页面自适应屏幕,小升初在线做试卷的网站,怎么样看网站用什么程序做的,东莞网站优化指导在理解原子变量之二#xff1a;从volatile到内存序-进一步的认识-CSDN博客里的实例3里面#xff0c;我们看到#xff0c;如果在一个线程里修改原子变量done#xff0c;另一个线程读取done时#xff0c;就会看到这个变化。这就是原子变量的可见性。其实这个认识是不全面的。…在理解原子变量之二从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 threadstd::atomicstd::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); // 绝无问题
//因为data42这句话发生在a线程写入原子变量之前
//所以在b线程读取原子变量后data的更新值对b线程是可见的
}int main()
{std::thread t1(producer);//这就是线程astd::thread t2(consumer);//这就是线程bt1.join(); t2.join();
}
尽管data是一个普通变量但是data42这个操作发生在ptr.store之前(且采用内存序release)所以consumer函数读取ptr.load之后(且采用内存序acquire)也可以看到data的最新值42
但是注意假如还有第三个线程且第三个线程不操作原子变量ptr,或者虽然操作ptr但是使用比较弱的内存序如前一篇所说的relaxed则release之前发生的写入操作的效果不一定能像使用acquire那样被第三个线程观察到。
在本系列第二篇的结尾曾经提到原子操作包含三个功能原子性、可见性和限制指令重排。我们已经在本系列第三篇交代了原子性--它是所有6个内存序都要满足的要求acquire和release当然不能例外本篇已经介绍了acquire和release的可见性那么下一篇就要介绍acquire和release如何限制指令重排。