原子操作(atomic operation)



参考博客:https://www.jianshu.com/p/440a629f50a2



1、概述

“原子操作(atomic operation)是 不需要 同步(synchronized)”,这是多线程编程的老生常谈了。
原子操作是指不会被 线程调度机制 打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。

1.1 定义

如果这个操作所处的层(layer) 的更高层不能发现其内部实现与结构,那么这个操作是一个原子(atomic) 操作。

原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分。

将整个操作视作一个整体是原子性的核心特征。

1.2 特性

原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断。


1.3 优点

从用户角度,可以用 原子操作 来替换 重量级锁同步,从而提高程序性能。
底层实现角度,原子操作 可以用于构建各种 更重量级的同步操作,比如锁或屏障之类的。


2、处理器如何实现原子操作

32位IA-32处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作。首先处理器会自动保证基本的内存操作的原子性。处理器保证从系统内存中读取或写入一个字节是原子的,意思是当一个处理器读取一个字节时,其他处理器不能访问这个字节的内存地址。Pentium 6和最新的处理器能自动保证单处理器对同一个缓存行里进行16/32/64位的操作是原子的,但是复杂的内存操作处理器是不能自动保证其原子性的,比如跨总线宽度、跨多个缓存行和跨页表的访问。但是,处理器提供总线锁定和缓存锁定两个机制来保证复杂内存操作的原子性。

2.1 使用 总线锁 保证原子性

第一个机制是通过总线锁保证原子性。如果多个处理器同时对共享变量进行读改写操作(i++就是经典的读改写操作),那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一致。举个例子,如果i=1,我们进行两次i++操作,我们期望的结果是3,但是有可能结果是2,如果所示:
在这里插入图片描述
原因可能是多个处理器同时从各自的缓存中读取变量i,分别进行加1操作,然后分别写入系统内存中。那么,想要保证读写改共享变量的操作是原子的,就必须保证CPU1读改写共享变量的时候,CPU2不能操作缓存了该共享变量内存地址的缓存。

处理器使用总线锁就是来解决这个问题的。所谓总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。

2.2 使用 缓存锁 保证原子性

第二个机制是通过缓存锁定来保证原子性。在同一时刻,我们只需保证对某个内存地址的操作是原子性即可,但总线锁定把CPU和内存之间的通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大,目前处理器在某些场合下使用缓存锁定代替总线锁定来进行优化。

猜你喜欢

转载自blog.csdn.net/Hongwei_1990/article/details/107595388