i++是原子操作吗?

原子操作:是不可被中断的

i++不是原子操作

分为3步:
<1> 先从内存中把i取出来放到寄存器中

<2>然后++,

<3>然后再把i复制到内存中,这需要至少3步

1. 什么是操作系统的“原子操作”
     原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断,分为两种情况(两种都应该满足)

     (1) 在单线程中, 能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间。

      (2) 在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。

 

2.   面试的时候经常问的一道题目是i++在两个线程里边分别执行100次,能得到的最大值和最小值分别是多少?(2 -200)

       i++只需要执行一条指令,并不能保证多个线程i++,操作同一个i,可以得到正确的结果。因为还有寄存器的因素,多个cpu对应多个寄存器。每次要先把i从内存复制到寄存器,然后++,然后再把i复制到内存中,这需要至少3步。从这个意义上讲,说i++是原子的并不对。
 

### 关于 `i++` 的原子性 在 C/C++ 中,`i++` 并不是一个原子操作。它实际上由三个独立的操作组成:加载当前值、增加该值以及存储新的值到变量中[^1]。这些操作通常不会作为一个整体被执行,而是被分解成多个指令,在多线程环境中可能会引发竞态条件。 为了使类似的自增操作具备原子性,C++ 提供了 `<atomic>` 头文件中的 `std::atomic` 类型及其成员函数。通过使用 `std::atomic<int> i;` 定义变量,并调用其提供的方法(如 `fetch_add()` 或 `operator++()`),可以确保整个操作在线程之间保持一致性和不可分割性。 下面是一个简单的例子展示如何利用 `std::atomic` 实现真正的原子递增: ```cpp #include <iostream> #include <thread> #include <atomic> std::atomic<int> counter(0); void increment() { for (int i = 0; i < 1000; ++i) { counter++; // 使用 std::atomic 的 operator++() } } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Final counter value: " << counter.load() << std::endl; } ``` 在这个程序里,即使两个线程同时访问并修改同一个全局变量 `counter`,由于它是声明为 `std::atomic<int>` 类型的,所以每次调用 `counter++` 都会以一种线程安全的方式完成加一动作。 另外需要注意的是,默认情况下所有的 atomic 操作都遵循顺序一致性 (`memory_order_seq_cst`) ,这意味着除了保证单个操作本身的原子性之外,还维护了一个全系统的偏序关系来协调不同处理器核心上的缓存刷新行为[^3]。不过也可以根据具体需求调整至更弱一些的记忆体排序选项比如 `memory_order_relaxed`, 这样虽然可能提高性能但是失去了某些同步保障。 综上所述,普通的整数类型上的 `i++` 不具有内在的原子特性;而借助标准库里的 `std::atomic` 则能轻易达成这一目标。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值