- 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 更新失敗和重試,所以需要慎用
- java.util.concurrent.atomic 包中的原子分為:原子性基本數據類型、原子性對象引用類型、原子性數組、原子性對象屬性更新器和原子性累加器
原子性基本數據類型:AtomicBoolean、AtomicInteger、AtomicLong
原子性對象引用類型:AtomicReference、AtomicStampedReference、AtomicMarkableReference
原子性數組:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
原子性對象屬性更新:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
原子性累加器:DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder
未使用原子類,測試代碼
package constxiong.interview;
/**
* JDK 原子類測試
* @author ConstXiong
*/
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 面試題 H5
- Java 面試題小程序