原子操作和非原子操作

今天在学习多线程时突然想到一个问题,CPU的CAS操作保证了原子性,但是现在的CPU都是多核心可以并行运算的多核CPU了,那CPU怎么实现并行运算时而又能保证对内存操作的原子性呢?

于是查阅了一些资料,有了以下了解:

  •     所谓原子操作,就是”不可中断的一个或一系列操作”

1.单核CPU的原子操作

  •     在单核CPU中, 能够在一个指令中完成的操作都可以看作为原子操作, 因为中断只发生在指令间.

也就是说单核CPU由于不存在多核心并行运算的情况,所有的操作其实都可以视为是原子的,就相当于我们如果只有一只手,就不能一边打字一边抠脚了,所以打字和抠脚的行为,变成了串行的行动,不能并行进行,所以都是原子性操作。
2.多核CPU的原子操作

  •     典型的例子就是decl指令(递减指令), 它细分为三个过程: “读->改->写”, 涉及两次内存操作. 如果多个CPU运行的多个进程在同时对同一块内存执行这个指令, 那情况是无法预测的.

可以看到多核CPU的情况下,就会出现类似我们多线程中出现的问题,对于同一块内存中的变量,多个核心同时读写修改数据的话,就会出现不可预期的错误。

那么CPU是怎么解决这个问题的呢?其实和我们软件平台实现思路很像,就是使用锁机制(回想一下JAVA中的同步锁)

  •     软件级别的原子操作是依赖于硬件支持的. 在x86体系中, CPU提供了HLOCK pin引线, 允许CPU在执行某一个指令(仅仅是一个指令)时拉低HLOCK pin引线的电位, 直到这个指令执行完毕才放开. 从而锁住了总线, 如此在同一总线的CPU就暂时无法通过总线访问内存了, 这样就保证了多核处理器的原子性. (想想这机制对性能影响挺大的).

通俗来讲就是你在被警察抓住了以后,一只手被手铐锁住,就只有另一只手能做事了,也就是说在执行原子操作时,CPU保证只有一个核心能对内存进行操作,这样以来就不会出现多个核心同时运算并回写内存的情况了
3.哪些操作可以确定为原子操作了?

  •     对于非long和double基本数据类型的”简单操作”都可以看作是原子的. 例如: 赋值和返回. 大多数体系中long和double都占据8个字节, 操作系统或者JVM很可能会将写入和读取操作分离为两个单独的32位的操作来执行, 这就产生了在一个读取和写入过程中一个上下文切换(context switch), 从而导致了不同任务线程看到不正确结果的的可能性.

递增, 递减不是原子操作: i++反汇编的汇编指令: (需要三条指令操作, 和两个内存访问, 一次寄存器修改)

  • // x86指令体系
  • movl i, %eax                            //内存访问, 读取i变量的值到cpu的eax寄存器
  • addl $1, %eax                         //增加寄存器中的值
  • movl %eax, i                            //写入寄存器中的值到内存

问:如何实现x++的原子性?

  •     在单处理器上,如果执行x++时,禁止多线程调度,就可以实现原子。因为单处理的多线程并发是伪并发。
  •     在多处理器上,需要借助cpu提供的Lock功能。锁总线。读取内存值,修改,写回内存三步期间禁止别的CPU访问总线。同时我估计使用Lock指令锁总线的时候,OS也不会把当前线程调度走了。要是调走了,那就麻烦了。

最后,我的一些理解和想法:

    1.对于CAS操作,编译器会自动汇编成CPU可以实现原子操作的汇编代码(不同CPU下实现可能不同,但是一定会借助某些锁实现汇编代码块的原子性)。
    2.使用CAS实现无锁同步的优点:减少操作系统阻塞线程的负担,直接使用硬件级别的锁必然要比在其之上的系统调用(比如OS实现的mutex互斥锁)更节省资源。
---------------------
作者:CringKong
来源:CSDN
原文:https://blog.csdn.net/CringKong/article/details/79966161
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值