赞
踩
CAS 比较并交换 Compare And Swap
,它是一种线程安全的原子语义操作,他的工作流程是:
针对一个变量,首先对变量进行修改,然后比较它的内存值和期望值进行比较,如果相同则将修改后的新值覆盖内存,否则什么都不处理。CAS的比较和交换两个步骤通过CPU的一个汇编指令执行,具有原子性,通常CAS可以看做是一种乐观锁的机制。
Java的CAS机制是通过unsafe类来进行API调用完成,例如对int变量的CAS操作,可以通过调用Unsafe#compareAndSwapInt()
来完成,但是这是一个native本地方法,是JNI链接通过C++代码实现。
Hotspor虚拟机对compareAndSwapInt()
的实现是通过调用Atomic::cmpxchg
方法完成,这个cmpxchg在不同的操作系统和CPU架构模式下都不一样,Linux_X86架构下,CAS最底层就是通过cmpxchgl
汇编指令来完成,但是因为CAS保证了原子性没有保证可见性,所以Hotspot在cmpxchgl
前加入了LOCK_IF_MP
判断是否为多核处理架构,如果是多核则在汇编指令前加入CPU的Lock前缀指令
来保证可见性问题。所以Java的CAS机制既能保证原子性也能保证可见性。
cmpxchgl
汇编指令本身没有自旋的功能,JDK中原子类和unsafe类提供的CAS是有while自旋操作的,但是如果在高并发场景下对共享变量修改时,会让大量的线程修改失败转而进行自旋,此时CPU会因此大量的自旋从而CPU开销变大,CPU利用率降低。并且,JVM在多核架构下还会添加Lock前缀指令
造成总线事务的攀升,总线事务嗅探也变得极为繁忙,总线带宽打满,进而造成总线风暴。
JDK提供了AtomicReference类来优化这个问题,但是并不是真正意义上保证多个变量,而是对对象进行CAS操作。
JDK提供了版本号机制AtomicStampedReference<V>
类,来解决ABA问题,就是每次修改时更新版本号。
AtomicMarkableReference<V>
类也能解决,只不过该类不关心版本变更了多少次,只关心是否发生了改变。
JDK的JUC包下的atomic
子包下提供了许多的原子类,他们都是基于CAS机制实现的线程安全的变量计算的类。这些类答题可以分为五大类:
- 基本类型原子类:AtomicInteger、AtomicLong、AtomicBoolean等
- 引用类型原子类:AtomicReference、AtomicStampedRerence、AtomicMarkableRerence
- 数组类型原子类:AtomicIntegerArray......等
- 对象属性原子类:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater等
- 原子类型累加器(JDK8):LongAdder、DoubleAdder、LongAccumulator、Striped64等。
- getAndIncrement() 获取原值,然后CAS增1。
- getAndSet() 获取原值,然后CAS设置新值。
- incrementAndGet() CAS增1,然后返回最新值。
- addAndGet(int index, int value) CAS形式对index位置的值变更为新值。
- getAndIncrement(int index) CAS形式对index位置的值自增1。
- compareAndSet(Object o1, Object o2) CAS方式将o1的引用赋值给o2。
Java在JDK8版本引入了LongAdder、DoubleAdder来优化高并发环境下的CAS自旋导致的性能消耗问题,他的设计理念就是热点分散
、分而治之
。不过LongAdder并不一定比AtomicLong等优秀,如果在低并发环境下,LongAdder着实有点杀鸡用牛刀的感觉,性能上甚至还不如用普通原子类。
LongAdder在CAS没有发生并发修改失败的场景下,就是对base的线性操作。如果一旦发生了冲突,那么线程就会将在Cell[ ]内操作各自独立负责的单元。而Cell数组的初始化和扩容的问题交给父类Striped64#longAccumulate()方法完成。
LongAdder的使命就是热点分散
。
该方法主要负责完成Cell[ ]的初始化工作和cell单元格CAS并发冲突时的解决、数组扩容的处理(2倍扩容)。
这个方法就是最后将Cell[ ]合并的方法,但是该方法并没有加锁处理,所以在高并发模式下,sum()方法的汇总统计结果可能会不准确,LongAdder只是近似准确的计数值。
它是对LongAdder的增强,LongAdder只能针对数值进行加减运算,而LongAccumulator提供了自定义函数计算。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。