std::atomic<int> volatile

《Effective Modern C++》学习笔记之条款四十:对并发使用std::atomic,对特种内存使用volatile_std::atomic和std::volitae-CSDN博客

现在事情应该明确了:

std::atomic对于并发程序设计有用,但不能用于访问特种内存。
volatile对于访问特种内存有用,但不能用于并发程序设计。

volatile std::atomic<int> val;      //针对val的操作是原子的,
                                    //并且不可以被优化掉

我们知道,std::atomic模板的实例(例如,std::atomic<int>、std::atomic<bool>和std::atomic<Widget* >等)提供的操作可以保证被其他线程视为原子的。一旦构造了一个std::atomic型别对象,针对它的操作就好像这些操作处于受互斥量保护的临界区域一样 ,但是实际上这些操作通常会使用特殊的机器指令来实现,这些指令比使用互斥量来的更加高效

考虑以下应用了std::atomic的代码:

std::atomic<int>  ai(0);        //将ai初始化为0
 
ai = 10;                        //将ai原子地设置为10
 
std::cout << ai;                //原子地读取ai的值
 
++ai;                           //原子地将ai自增为11
 
--ai;                           //原子地将ai自减为10

因此,将valAvailable声明为std::atomic型别可以确保我们的关键顺序需求得到保证,impValue必须被所有线程看到,它是以不晚于valAvailable的时序被更改。

std::atomic<bool>  valAvailable(false);
 
auto impValue = computeImportValue();       //计算值
 
valAvailable = true;                        //通知其他任务值已可用

//volatile不能保证顺序
volatile bool  valAvailable(false);
 
auto impValue = computeImportValue();       //计算值
 
valAvailable = true;        //其他线程可能将这个赋值操作视作
                            //在impValue之前!

在这里,编译器可能会将赋值顺序反转为后impValuevalAvailable,即使它不这么做, 也可能不会生成及其代码阻止底层硬件使其他内核上的代码看到valAvailableimpValue之前发生改变。

这两个那问题(无法保证操作的原子性,无法对代码重新排序施加限制)解释了为何volatile并发编程没用,但是并未解释它在什么情况下有用。简而言之,它的用处就是告诉编译器,正在处理的内存不具备常规行为

特种内存
此类优化仅在内存行为符合常规时才合法。“特种”内存就是另一回事。

可能最常见的特种内存是用于内存映射IO的内存。这种内存的位置实际上是用于与外部设备(例如,外部传感器、显示器、打印机和网络端口等)通信,而非用于读取或写入常规内存(即RAM)。

而volatile的用处就是告诉编译器,正在处理的是特种内存。它的意思是通知编译器“不要对在此内存上的操作做任何优化”。所以,如果x对应于特种内存,则它应该加上volatile声明饰词:

由于移动操作没有在std::atomic中显示声明,因此,根据Item 17中描述的编译器生成特种函数的规则,std::atomic既不提供移动构造,也不提供移动赋值运算符。

从x中取值并置入y是可以实现的,但是要求使用std::atomic的成员函数load和store。load成员函数以原子方式读取std::atomic型别对象的值,而store成员函数以原子方式写入之。如果想先用x初始化y,然后将x的值置入y,代码必须如下撰写:

std::atomic<int>  y(x.load());          //读取x
y.store(x.load());                      //x再次读取


register = x.load();                //将x读入寄存器
std::atomic<int>  y(register);      //以寄存器值初始化y
y.store(register);                  //将寄存器值存储入y

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值