操作系统中存在一旦执行则要么执行完成要么不能执行的操作,这类操作具有良好的并行安全特性,被称为
原子操作
。
简介
原子操作(atomic operation)指的是由多步操作组成的一个操作。如果该操作不能原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。
现代操作系统中,一般都提供了原子操作来实现一些同步操作,所谓原子操作,也就是一个独立而不可分割的操作。在单核环境中,一般的意义下原子操作中线程不会被切换,线程切换要么在原子操作之前,要么在原子操作完成之后。更广泛的意义下原子操作是指一系列必须整体完成的操作步骤,如果任何一步操作没有完成,那么所有完成的步骤都必须回滚,这样就可以保证要么所有操作步骤都未完成,要么所有操作步骤都被完成。
在单核系统里,单个的机器指令可以看成是原子操作(如果有编译器优化、乱序执行等情况除外);在多核系统中,单个的机器指令就不是原子操作,因为多核系统里是多指令流并行运行的,一个核在执行一个指令时,其他核同时执行的指令有可能操作同一块内存区域,从而出现数据竞争现象。多核系统中的原子操作通常使用内存栅障(memory barrier)来实现,即一个CPU核在执行原子操作时,其他CPU核必须停止对内存操作或者不对指定的内存进行操作,这样才能避免数据竞争问题。
何时使用
在多线程并发的条件下,所有不是原子性的操作需要保证原子性时,都需要进行原子操作处理。
windows 原子操作 api
Win32 API中常用的原子操作主要有三类,一种是
加1减1操作
,一种是比较交换
操作,另外一种是赋值(写)
操作。
原子加1减1操作
代码语言:javascript复制LONG InterlockedIncrement( LONG volatile* Addend);
LONG InterlockedDecrement( LONG volatile* Addend);
比较并交换(Compare And Swap, CAS)操作
代码语言:javascript复制LONG InterlockedCompareExchange( LONG volatile*Destination, LONG Exchange, LONG Comperand );
这个操作是先将Comperand的值和Destination指向变量的值进行比较,如果相等就将Exchange变量的值赋给Destination指向的变量。返回值为未修改前的Destination位置的初始值。
原子写操作
代码语言:javascript复制LONG InterlockedExchange( LONG volatile* Target, LONG Value);
InterlockedExchange的作用为将Value的值赋给Target指向的变量,返回Target指向变量未被赋值前的值。
并发安全
多线程
原子操作对于多线程并发是线程安全的,一个线程在执行原子操作时其他线程无法介入其中间过程,无法读、修改或打断该操作。
多进程
对于多进程也是有效的, 因为原子变量操作时是锁总线的,这个动作是在硬件层面来做的,他比操作系统更加底层,进程只是操作系统层面的概念,那么跨进程就更不再话下了。
参考资料
- 原子操作
- 原子操作对建立在跨进程的共享内存上的变量有效吗
- Atomic Operations in OS
文章链接: https://cloud.tencent.com/developer/article/2345860