- JDK Atomic開頭的類,是通過 CAS 原理解決並發情況下原子性問題。
- CAS 包含 3 個參數,CAS(V, E, N)。V 表示需要更新的變量,E 表示變量當前期望值,N 表示更新為的值。只有當變量 V 的值等於 E 時,變量 V 的值才會被更新為 N。如果變量 V 的值不等於 E ,說明變量 V 的值已經被更新過,當前線程什么也不做,返回更新失敗。
- 當多個線程同時使用 CAS 更新一個變量時,只有一個線程可以更新成功,其他都失敗。失敗的線程不會被掛起,可以繼續重試 CAS,也可以放棄操作。
- CAS 操作的原子性是通過 CPU 單條指令完成而保障的。JDK 中是通過 Unsafe 類中的 API 完成的。
- 在並發量很高的情況,會有大量 CAS 更新失敗,所以需要慎用。
未使用原子類,測試代碼
package constxiong.interview; /** * JDK 原子類測試 * @author ConstXiong * @date 2019-06-11 11:22:01 */ public class TestAtomic { private int count = 0; public int getAndIncrement() { return count++; } // private AtomicInteger count = new AtomicInteger(0); // // public int getAndIncrement() { // return count.getAndIncrement(); // } public static void main(String[] args) { final TestAtomic test = new TestAtomic(); for (int i = 0; i <3; i++) { new Thread(){ @Override public void run() { for (int j = 0; j <10; j++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 獲取遞增值:" + test.getAndIncrement()); } } }.start(); } } }
打印結果中,包含重復值
Thread-0 獲取遞增值:1
Thread-2 獲取遞增值:2
Thread-1 獲取遞增值:0
Thread-0 獲取遞增值:3
Thread-2 獲取遞增值:3
Thread-1 獲取遞增值:3
Thread-2 獲取遞增值:4
Thread-0 獲取遞增值:5
Thread-1 獲取遞增值:5
Thread-1 獲取遞增值:6
Thread-2 獲取遞增值:8
Thread-0 獲取遞增值:7
Thread-1 獲取遞增值:9
Thread-0 獲取遞增值:10
Thread-2 獲取遞增值:10
Thread-0 獲取遞增值:11
Thread-2 獲取遞增值:13
Thread-1 獲取遞增值:12
Thread-1 獲取遞增值:14
Thread-0 獲取遞增值:14
Thread-2 獲取遞增值:14
Thread-1 獲取遞增值:15
Thread-2 獲取遞增值:15
Thread-0 獲取遞增值:16
Thread-1 獲取遞增值:17
Thread-0 獲取遞增值:19
Thread-2 獲取遞增值:18
Thread-0 獲取遞增值:20
Thread-1 獲取遞增值:21
Thread-2 獲取遞增值:22
測試代碼修改為原子類
package constxiong.interview; import java.util.concurrent.atomic.AtomicInteger; /** * JDK 原子類測試 * @author ConstXiong * @date 2019-06-11 11:22:01 */ public class TestAtomic { // private int count = 0; // // public int getAndIncrement() { // return count++; // } private AtomicInteger count = new AtomicInteger(0); public int getAndIncrement() { return count.getAndIncrement(); } public static void main(String[] args) { final TestAtomic test = new TestAtomic(); for (int i = 0; i <3; i++) { new Thread(){ @Override public void run() { for (int j = 0; j <10; j++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 獲取遞增值:" + test.getAndIncrement()); } } }.start(); } } }
打印結果中,不包含重復值
Thread-0 獲取遞增值:1
Thread-2 獲取遞增值:2
Thread-1 獲取遞增值:0
Thread-0 獲取遞增值:3
Thread-1 獲取遞增值:4
Thread-2 獲取遞增值:5
Thread-0 獲取遞增值:6
Thread-1 獲取遞增值:7
Thread-2 獲取遞增值:8
Thread-0 獲取遞增值:9
Thread-2 獲取遞增值:10
Thread-1 獲取遞增值:11
Thread-0 獲取遞增值:12
Thread-1 獲取遞增值:13
Thread-2 獲取遞增值:14
Thread-0 獲取遞增值:15
Thread-1 獲取遞增值:16
Thread-2 獲取遞增值:17
Thread-0 獲取遞增值:18
Thread-1 獲取遞增值:19
Thread-2 獲取遞增值:20
Thread-0 獲取遞增值:21
Thread-2 獲取遞增值:23
Thread-1 獲取遞增值:22
Thread-0 獲取遞增值:24
Thread-1 獲取遞增值:25
Thread-2 獲取遞增值:26
Thread-0 獲取遞增值:27
Thread-2 獲取遞增值:28
Thread-1 獲取遞增值:29
- Java 自學指南
- Java 面試題匯總PC端瀏覽【點這里】
- Java知識圖譜
- Java 面試題匯總小程序瀏覽,掃二維碼
所有資源資源匯總於公眾號