原子操作简介
原子操作(Atomic Operation)是一种不可分割的操作,要么完全执行成功,要么完全不执行。原子操作的执行过程中不允许有任何中断,如果出现了中断,那么操作的结果就无法保证。原子操作通常用于多线程编程中,保证多个线程之间的并发执行不会出现数据竞争等问题。在实现原子操作时,通常使用硬件指令或者操作系统提供的原子操作函数来保证操作的原子性。在应用层面,原子操作可以用于实现一些高级的同步和并发控制机制。例如,在多线程编程中,如果多个线程都需要访问同一个共享变量,为了避免数据竞争问题,可以使用原子操作来保证对该变量的操作是原子的。以ARM内核执行一个i++操作为例:
movl i, %eax //内存访问,读取 i 变量到 cpu 的 eax 寄存器
addl $1, %eax //修改寄存器的值
movl %eax, i //将寄存器中的值写回内存
可以看到对于编码的工程师,执行一个i++的操作仅需一行代码,在编译后i++就会被翻译成三条指令,所以在这三条指令之间是可能会被系统调用、中断等事件打断的,因而我们在一些场景就需要一气呵成完成上述操作,原子操作就具备这样的能力。
原子操作的优点
通常,在操作系统中,可以采取开关全局中断、调度器上锁等方式对临界区资源进行保护,其他OS也会提供类似的操作,若采用原子操作后可以提供临界区代码的执行效率,大幅度提升系统的运行效率,同时也会在一定程度上降低编程的复杂度。下面是一个简单变量的自增示例:
采用开关全局变量的方式实现对临界区的保护:
...
int a = 5;
关闭全局中断
a++;
打开全局中断
...
在我们的RT-Thread中,该操作系统提供了原子操作的API:
...
int a = 5;
rt_atomic_add(&a,1);
...
显然采用原子操作的方式更加简单直接,且避免了开关全局中断的性能损失。但是该方式并不能完全避免在多线程下完全保证原子性。
感兴趣的朋友可以查下官员原子操作的函数API。百度下Linux的原子操作源码即可。