聊聊 volatile 關鍵字
我們知道volatile關鍵字的作用是保證變數在多執行緒之間的可見性,它是java.util.concurrent包的核心,沒有volatile就沒有這麼多的併發類給我們使用。本文將簡單介紹一下volatile這個東東。
演算法概念及其執行流程
- CAS(compare-and-swap)是一種硬體對併發的支援,針對多處理器操作而設計的處理器中的一種特殊指令,用於管理對共享資料的併發訪問。
- CAS 是一種無鎖非阻塞演算法的實現。
-
CAS 包含了 3 個運算元:
需要讀寫的記憶體值 V
進行比較的值 A
擬寫入的新值 B
-
當且僅當 V 的值等於 A 時,CAS 通過原子方式用新值更新 V 的值,否則不會執行任何操作。
CAS 操作過程如下所示
CAS 演算法模擬
/** * 模擬 CAS 演算法 * * Created by wuhf on 2017-1-22. */ 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 expectValue = cas.getValue(); boolean b = cas.compareAndSet(expectValue, (int)(Math.random() * 101)); System.out.println(b); } } ).start(); } } } class CompareAndSwap{ private int value; // 獲取記憶體值 public synchronized int getValue(){ return this.value; } // 比較 public synchronized int compareAndSwap(int expectValue,int newValue){ int oldValue = this.value; if(oldValue == expectValue){//如果期望值等於舊值 this.value = newValue; } return oldValue; } public synchronized boolean compareAndSet(int expectValue,int newValue){ return expectValue == compareAndSwap(expectValue, newValue); } }
原子變數
-
類的小工具包,支援在單個變數上解除鎖的執行緒安全程式設計。事實上,此包中的類可將 volatile 值、欄位和陣列元素的概念擴充套件到那些也提供原子條件更新操作的類。
-
類 AtomicBoolean、 AtomicInteger、 AtomicLong 和 AtomicReference 的例項各自提供對相應型別單個變數的訪問和更新。每個類也為該型別提供適當的實用工具方法。
-
AtomicIntegerArray、 AtomicLongArray 和 AtomicReferenceArray 類進一步擴充套件了原子操作,對這些型別的陣列提供了支援。這些類在為其陣列元素提供 volatile 訪問語義方面也引人注目,這對於普通陣列來說是不受支援的。
-
核心方法: boolean compareAndSet(expectedValue, updateValue)
-
java.util.concurrent.atomic 包下提供了一些原子操作的常用類:
- AtomicBoolean 、 AtomicInteger 、 AtomicLong 、AtomicReference
- AtomicIntegerArray 、 AtomicLongArray
- AtomicMarkableReference
- AtomicReferenceArray
- AtomicStampedReference
原子變數簡單 Demo
/** * 一、i++ 的原子性問題:i++ 的操作實際上分為三個步驟“讀-改-寫” * int i = 10; * i = i++; //10 * * int temp = i; * i = i + 1; * i = temp; * 二、原子變數:在 java.util.concurrent.atomic 包下提供了一些原子變數。 * 1. volatile 保證記憶體可見性 * 2. CAS(Compare-And-Swap) 演算法保證資料變數的原子性 * CAS 演算法是硬體對於併發操作的支援 * CAS 包含了三個運算元: * 1,記憶體值V * 2,預估值A * 3,更新值B * 當且僅當 V == A 時, V = B; 否則,不會執行任何操作。 */ public class AtomicDemo { public static void main(String[] args) { AtomicData ad = new AtomicData(); for (int i = 0; i < 10; i++) { new Thread(ad).start(); } } } class AtomicData implements Runnable{ // 初始化原子變數 private AtomicInteger atomicData = new AtomicInteger(0); @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getAtomicData()); } // 相當於atomicData++ public int getAtomicData(){ return atomicData.getAndIncrement(); } }