天天看點

Java JUC 進階線程之二 原子變量和CAS算法

文章目錄

    • 原子變量
    • CAS算法
    • 執行個體dome
    • 模拟CAS算法

原子變量

  1. 類的小工具包,支援在單個變量上解除鎖的線程安全程式設計。事實上,此包中的類可将 volatile值、字段和數組元素的概念擴充到那些也提供原子條件更新操作的類。
  2. 類 AtomicBoolean、 AtomicInteger、 AtomicLong和 AtomicReference的執行個體各自提供對相應類型單個變量的通路和更新。每個類也為該類型提供适當的實用工具方法。
  3. AtomicIntegerArray、 AtomicLongArray和 AtomicReferencearray類進一步擴充了原子操作,對這些類型的數組提供了支援。這些類在為其數組元素提供 volatile通路語義方面也引人注目,這對于普通數組來說是不受支援的。
  4. 核心方法:boolean compareAndSet(expectedValue,updateValue);
  5. java.util.concurrent.atomic包下提供了一些原子操作的常用類:
    1. AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
    2. AtomicIntegerArray、AtomicLongArray
    3. AtomicMarkableReference
    4. AtomicReferenceArray
    5. AtomicStampedReference

CAS算法

  1. CAS( Compare-And-Swap)是一種硬體對并發的支援,針對多處理器操作而設計的處理器中的一種特殊指令,用于管理對共享資料的并發通路。
  2. CAS是一種無鎖的非阻塞算法的實作。
  3. CAS包含了3個操作數
    1. 需要讀寫的記憶體值V
    2. 進行比較的值A
    3. 拟寫入的新值B
  4. 當且僅當v的值等于A時,CAS通過原子方式用新值B來更新V的值,否則不會執行任何操作。

執行個體dome

注釋部分為原來的代碼。

/*
 * 一、 i++ 的原子性問題:i++ 的操作實際上分為三個步驟“讀-改-寫”
 * 
 * 			int i = 10;
 * 			i = i++;//10
 * 
 * 			int temp = i;
 * 			i = i + 1;
 * 			i = temp;
 * 二、 原子變量:jdk1.5 後java.util.concurrent.atomic 包下提供了常用的的原子變量
 * 		1. 裡面封裝的value 都用 volatile修飾 保證記憶體可見性
 * 		2. CAS(Compare-And-Swap) 算法保證資料的原子性
 * 			CAS 算法是硬體對于并發操作共享資料的支援
 * 			CAS 包含了三個操作數:
 * 				記憶體值 V
 * 				預估值 A
 * 				更新值 B
 * 				當且僅當 V == A 時,才會把 B的值賦給A,否則,不做任何操作。
 */
public class TestAtomicDemo {
	
	public static void main(String[] args) {
		
		AtomicDemo ad = new AtomicDemo();
		
		for (int i = 0; i < 10; i++) {
			new Thread(ad).start();
		}
		
	}
}
class AtomicDemo implements Runnable{

//	private volatile int serialNumber = 0;
	private AtomicInteger serialNumber = new AtomicInteger();
	@Override
	public void run() {
		
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println(Thread.currentThread().getName() + " : " + getSerialNumber());
	}
	
	public int getSerialNumber() {
//		return serialNumber++;
		return serialNumber.getAndIncrement();
	}

}
           

模拟CAS算法

這段代碼有點難了解,看不懂可以留言。

/*
 * 模拟cas算法
 */
public class TestCompareAndSwap {
	public static void main(String[] args) {
		
		final CompareAndSwap cas = new CompareAndSwap();
		
		for (int i = 0; i < 10; i++) {
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					int expectedValue = cas.get();
					int i = (int)(Math.random()*101);
					System.out.println(expectedValue+ " " +i);
					boolean b = cas.compareAndSet(expectedValue, i);
					System.out.println(b);
				}
			}).start();;
		}
	}
}
class CompareAndSwap{
	
	private int value;
	//擷取記憶體值
	public synchronized int get() {
		return value;
	}
	
	//比較
	public synchronized int compareAndSwap(int expectedValue, int newValue) {
		
		int oldValue = value;
		
		if(oldValue == expectedValue) {
			this.value = newValue;
		}
		
		return oldValue;
	}
	
	//設定
	public synchronized boolean compareAndSet(int expectedValue,int newValue) {
		return expectedValue == compareAndSwap(expectedValue, newValue);
	}
	
}
           

繼續閱讀