之前的博客简单提到了CAS保证数据一致性的简单原理,通过一个i++ 的简单原理说明了CAS通过一个预期值的检查来确定当前线程是否被抢占。这次通过将站在编译器与CPU的角度深入理解CAS的原理与缓存一致性等一系列问题。部分引用自《java并发编程的艺术》。
首先还是来看看++i是怎么做到的。
在这里采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。(最新的jdk1.8是看不到具体代码的,而是封装在unsafe类里面不过代码是差不多的)<span style="font-family:SimSun;font-size:14px;">public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } }</span>
而compareAndSet利用JNI来完成CPU指令的操作。
整体的过程就是这样子的,利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法。其它原子操作都是利用类似的特性完成的。<span style="font-family:SimSun;font-size:14px;">public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }</span>
CAS