原子(atomic)本意时“不能被进一步分割的最小粒子”,而原子操做(atomic operation)意为“不可被中断的一个或一系列操做”。java
在 Java 中能够经过锁和循环 CAS 的方式实现原子操做。安全
一、使用循环 CAS 实现原子操做多线程
JVM 中的 CAS 操做正是利用了处理器提供的 CMPXCHG 指令实现的。自旋 CAS 实现的基本思路就是循环进行 CAS 操做直到成功为止,如下代码实现了一个基于 CAS 线程安全的计数器方法 safeCount 和一个非线程安全的计数器 count。atom
import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * Author: YiFan * Date: 2018/11/25 20:39 * Description: CAS操做 */ public class CASTest { private AtomicInteger atomicI = new AtomicInteger(0); private int i = 0; public static void main(String[] args) throws InterruptedException { final CASTest cas = new CASTest(); List<Thread> threads = new ArrayList<>(600); long start = System.currentTimeMillis(); for (int i = 0; i < 100; i++) { Thread t = new Thread(() -> { for (int j = 0; j < 10000; j++) { cas.count(); cas.safeCount(); } }); threads.add(t); } for (Thread t: threads ) { t.start(); } // 等待全部线程执行完成 for (Thread t: threads ) { t.join(); } System.out.println(cas.i); System.out.println(cas.atomicI.get()); System.out.println(System.currentTimeMillis() - start); } // 非线程安全计数器 private void count() { i++; } // 使用CAS实现线程安全计数器 private void safeCount() { for (;;) { int i = atomicI.get(); boolean suc = atomicI.compareAndSet(i, ++i); if (suc) { break; } } } }
该示例演示了多线程下对共享变量进行操做,count 方法中没有使用 CAS 操做,致使多个线程能够同时对共享变量 i 进行操做,因此致使最终的 i 值不为 100000。可是 safeCount 方法中使用了 CAS 操做,这样就解决的多线程下对 i++ 的原子性操做了,因此最终 i 值始终为 100000。线程
二、使用锁机制实现原子操做code
锁机制保证了只有得到锁的线程才可以操做锁定的内存区域。JVM 内部实现了不少种锁机制,有偏向锁、轻量级锁和互斥锁。其中 JVM 实现锁的方式都用了循环 CAS,即当一个线程想进入同步块的时候使用循环 CAS 的方式来获取锁,当他退出同步块的时候使用循环 CAS 释放锁。ip