第 4 章 Java 并发包中原子操作类原理剖析
原子变量操作类
- AtomicLong 是原子性递增或者递减类,其内部使用 Unsafe 来实现,AtomicLong类也是在 rt.jar 包下面的,AtomicLong 类就是通过 BootStarp 类加载器进行加载的。
- 这里的原子操作类都使用 CAS 非阻塞算法
private static final long serialVersionUID = 1927816293512124184L; // (1)获取Unsafe实例 private static final Unsafe unsafe = Unsafe.getUnsafe(); //(2)存放变量value的偏移量 private static final long valueOffset; //(3)判断JVM是否支持Long类型无锁CAS static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); private static native boolean VMSupportsCS8(); static { try { //(4)获取value在AtomicLong中的偏移量 valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //(5)实际变量值 private volatile long value; public AtomicLong(long initialValue) { value = initialValue; } .... }
LongAdder 简单介绍
- AtomicLong 通过 CAS 提供了非阻塞的原子性操作,相比使用阻塞算法的同步器来说它的性能已经很好了,但是 JDK 开发组并不满足于此。使用 AtomicLong 时,在高并发下大量线程会同时去竞争更新同一个原子变量,但是由于同时只有一个线程的CAS 操作会成功,这就造成了大量线程竞争失败后,会通过无限循环不断进行自旋尝试 CAS 的操作,而这会白白浪费 CPU 资源。
- 因此 JDK 8 新增了一个原子性递增或者递减类 LongAdder 用来克服在高并发下使用 AtomicLong 的缺点。既然 AtomicLong 的性能瓶颈是由于过多线程同时去竞争一个变量的更新而产生的,那么如果把一个变量分解为多个变量,让同样多的线程去竞争多个资源, 是不是就解决了性能问题?是的,LongAdder 就是这个思路。
CHAPTER-FOUR OVER.......
PROCESS--->4/11