Java並發原子類有哪些?如何使用?


  • 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


原文鏈接
 


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM