1.什么是原子操作在多线程环境下,原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程) 。
原子操作可以确保某些特定操作在多线程条件下,不会由于线程切换而导致数据污染 。比如,对一个变量的读/写操作,就是一个常见的需要原子化的场景 。如果把这样的读/写操作设计成原子操作,就可以避免多线程竞争导致的数据不一致问题 。

文章插图
2.++i 是否原子操作在 C++ 中,对一个变量的自增(++)操作看似很简单,理论上它包含:
- 读变量原值
- 对原值加 1
- 将结果写回变量
int i = 0; ++i;但是在多线程环境下,这三个步骤如果被打断,可能导致如下结果:- 线程1 读到i=0
- 线程2也读到i=0
- 线程1对i加1并写入,现在i=1
- 线程2对i加1并写入,这时覆盖了线程1的写入,又使得i=1
为了避免上述情况,C++编译器在编译过程中,会自动将一些看似简单的操作(例如自增操作)转换为原子指令,从而保证其原子性 。
【C++ 里 ++i 是原子操作吗?】这种特性与具体的编译器实现相关,比如主流的GNU编译器和MSVC编译器都对自增操作进行了优化,确保其原子执行 。
所以可以认为,在绝大多数C++实现中,++i这个自增操作是原子的 。但是仍有一些例外情况需要注意,比如在嵌入式平台上可能需要开发者显式指定操作的原子性 。
3. 如何保证操作的原子性在不能依赖编译器优化的情况下,C++11提供了一些方法可以保证操作的原子性:
(1) atomic类型:提供了一些原子类型,对其操作天然原子
int i = 0; ++i;(2) mutex:使用mutex可以在临界区内执行一个原子块std::mutex m;m.lock();// critical sectioncnt++; m.unlock();(3) lock-free编程:通过CAS(compare-and-swap)等原子指令实现非阻塞同步atomic_int val;int expect = val.load();while(!val.compare_exchange_weak(expect, expect + 1)) {expect = val.load(); } atomic_int val;int expect = val.load();while(!val.compare_exchange_weak(expect, expect + 1)) {expect = val.load(); }4. 总结综上所述,在大多数普通的桌面程序和服务端程序中,++i这样的自增操作可以看作是原子的,编译器会做出优化 。但是对于嵌入式开发等要求原子操作显式控制的场景,C++11提供了一些新的原子类型和同步原语来保证操作的原子执行 。推荐阅读
- 使用二进制字面量在现代C++中的应用
- 为什么在 C++14 中删除了 get 函数?
- 郭嘉文重新出道,秀瑜伽身材健身运动,和梁洛施暗地里较劲
- 蒸笼清洗方法有哪些 蒸笼清洗方法
- 怎样在微信里找回删除的聊天记录视频 怎样在微信里找回删除的聊天记录
- ios微信拍一拍功能在哪里 ios微信拍一拍怎么开
- 今日靓汤:核桃瘦肉海马汤
- 汽车安全气囊里充入的主要是什么气体 汽车安全气囊里充入哪种气体
- 保鲜膜能在微波炉里加热吗 保鲜膜能在微波炉中加热吗
- 夏日荷花冰凉宴
