原子操作的实现原理
1、原子操作是不可被中断的一个活一系列的操作。
首先我们看一下几个术语:
1、缓存行:缓存最小的操作单位
2、CAS:比较并交换,从他的英文拼写也许更直观:Compare and Swap,CAS的操作就是需要输入两个值,一个是旧值一个是新值,当操作期间先比较旧值有没有变化,没有才更新新值,有就更新失败。
3、CPU流水线:一个CPU中是有5-6个不同功能的电路单元组成的一条指令流水线,当CPU接受到一条指令,会先分成5-6步之后再由这些电路单元进行执行,这样就在CPU的一个时钟周期内完成一条指令提高CPU的运算速度。
4、内存顺序冲突:内存顺序冲突一般有假共享内存引起,假共享内存是指多个CPU同时修改同一个缓存行的不同部分而引起的其中一个CPU的操作无效,当出现缓存冲突的时候需要CPU清空流水线。
了解了这些属于概念,我们看下处理器是如何做到原值操作。
处理器是使用缓存加锁或者总线加锁的机制来实现多个处理器之间的原子操作,处理器从系统内存中读取或着写一个内存的时候保证原子的,就是一个处理器在操作这个内存是其他的处理器不能操作这个内存地址。
1.使用总线保证原子性:
当使用总线锁保证原子性的时候就想咱们通常使用的重量级锁,当CPU1操作这个共享变量的时候其他的CPU只能阻塞等待锁释放。开销比较大
2、使用缓存锁保证原子性:
因为通常使用的数据会缓存在CPU的L1,L2,L3级高速缓存中,那么使用总线锁的开销就会有些大,那么使用缓存锁来保证原子性就会高效的多,使用缓存锁就是数据在CPU的缓存中,那么久可以申明Lock在和缓存上而不是在总线上,那么在锁定期间缓存回写内存的时候会修改内存地址,并允许他的缓存一致性保证原子性,缓存一致性会阻止同时修改由两个以上的处理器缓存的内存区域数据,当另一个CPU进行回写的时候,缓存行会无效。
但是我们需要注意的是两种情况下CPU不会使用缓存锁,
1、操作的数据不能存放在处理器内部,或者操作的数据跨多个缓存行时。处理器会使用总线锁。
2、有些处理器不支持缓存锁。
3.了解了CPU是如何保证原子性的,那么java是如何保证原子性的呢。
1.使用CAS自旋来实现操作的原子性。
2.使用锁来实现原子性(偏向锁、轻量级锁、重量级索(互斥锁))
但是CAS也有些弊端
1.循环时间长,消耗CPU。
2.只能保证一个变量的原子操作。