原子(atomic)在物理上的定义是,不能被分割的最小的粒子。而在Java中,原子操作指的是不能被中断的一个或一系列操作。那么Java里面是如何实现原子操作的呢?
第一个方法是循环CAS
先简单说明一下什么是CAS。
CAS即compare and swap,比较并交换。CAS操作包含三个操作数:内存位置(V),预期原值(A),新值(B)。比较和交换就体现在这三个操作数上面,如果内存位置的值与预期原值相匹配,那么处理器会自动将新值更新到该内存位置,如果不匹配,处理器就不做操作。JVM中的CAS操作也正是利用了处理器提供的cmpxchg指令来实现的。
下面看一段循环CAS的代码来做进一步的了解:
最终结果不一致的原因是多个处理器同时从自己的缓存中读取变量i,各自加1后又放入内存,unsafeCount()方法不能保证原子性,因为多个处理器有可能同时执行i++操作,所以结果就如图所示。
从JDK 1.5开始,并发包里提供了一些类来支持原子操作,比如刚用到的AtomicInteger类。
第二个方法是锁
锁机制保证了只有获得锁的线程才可以操作锁定的内存区域。JVM中除了偏向锁,其他的锁都用了循环CAS的方式来获取锁和释放锁。