effective c++ 条款40 并发场景使用std::atomic ,特殊内存场景使用volatile

可怜的volatile,被误解如此之深,就不应该出现在本章,因为它和并发编程毫无关系。但在其他语言(java或者c#),它在并发编程中很用。在某些c++编辑器中,volatile被赋予了特殊语义,使其可以用在并发编程中(但也只有用这些编译器编译才可以用)。即使为了澄清围绕它产生的误解,在关于并发编程的本章中探讨一下volatiile也是有价值的。

c++容易混淆属于volatile和std::atoimic模板的特征。模板的实例化(如std::atoimic<int> std::atomic<bool>和std::atomic<Widget*>)提供了不同线程之间的原子操作。一旦std::atomic对象构建出来,对其访问,就如同在mutex保护的关键代码中访问一样。然而这些操作由特殊的机器指令来实现,比使用mutex保护的效率要高很多。

考虑下面使用std::atomic的代码:

std::atomic<int> ai(0);        //初始化ai为0

ai = 10;                             //原子设置ai为10

std::cout << ai;                  //原子打印ai

ai++;                               // 原子增加ai到11

--ai ;                              //原子减小ai到10

在这些语句操作过程中,别的线程读取ai的值只可能为(0,10,11,10)。别的值都不可能出现(当然我们假定了只有一个线程更改)

上面例子中两个语句值得一提。一个是std::cout << ai。因为事实上std::atomic只保证读取ai是原子操作,并不保证整条语句都是原子的。在读取ai和<<操作输出到标准输出之间,别的线程可能会更改ai的值。这对输出无影响,因为int 的<<操作是值传递(所以智慧输出读取到的值)。但重要的是要理解,这条语句中的原子操作不过是单指读取ai。

另外一个值得一提的是最后两个语句的行为——自增和自减。它们每个都是读改写(RMW)操作,因此它们进行原子操作。这是std::atomic类型最优雅之处,一旦一个std::atomic对象创建出来,所有成员函数操作,包括自增和自减之类的(RMW)都是原子操作。

相反,多线程上下文使用volatile什么都不会保证

volatile int vi(0);//初始化为0

vi=10;                   //设置vi为10

std::cout << vi

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值