從AtomicInteger到AQS原理
阿新 • • 發佈:2019-12-31
什麼是AtomicIntger
- AtomicIntger是對int型別的一個封裝,它提供了原子自增方法、原子自減方法以及原子賦值方法,即提供原子性的訪問和更新操作。其中volatile保證了記憶體可見性(volatile這裡在Java記憶體模型和volatile、synchronized裡面講過,不瞭解的可以跳過去看看),其原子性操作的實現是基於CAS(compare-and-swap)技術。
- 所謂CAS,就是獲取某個數值的標誌位,儲存下來,然後再利用CAS指令試圖進行更新。如果當前標誌位數值未變,代表沒有其他執行緒進行併發修改這個數值,則成功更新。否則,可能出現不同的選擇,要麼進行重試,要麼就返回一個成功或者失敗的結果。
- 從AtomicInteger的內部屬性可以看出,它依賴於Unsafe提供的一些底層能力,進行底層操作;以volatile的value欄位,記錄數值,以保證可見性。
- CAS是Java併發中所謂lock-free機制的基礎。
AQS
理解為什麼需要AQS,如何使用AQS,至少要做什麼,再進一步結合JDK原始碼中的實踐,理解AQS的原理與應用
什麼是AQS
AQS是AbstactQueuedSynchronizer的簡稱,它是一個Java提高的底層同步工具類,用一個int型別的變數 --state 表示同步狀態,並提供了一系列的CAS操作來管理這個同步狀態。AQS的主要作用是為Java中的併發同步元件提供統一的底層支援,用法是通過繼承AQS實現其模版方法,然後將子類作為同步元件的內部類。比如ReentrantLock裡面的子類Sync:
public class ReentrantLock implements Lock,java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
...
}
}
複製程式碼
AQS內部資料和方法,可以簡單拆分為:
- 一個volatile的整數成員表徵狀態,同時提供了setState和getState方法
private volatile int state;
複製程式碼
- 一個先入先出(FIFO)的等待執行緒佇列,以實現多執行緒間競爭和等待,這是AQS機制的核心之一。
//內部類Node
static final class Node
複製程式碼
- 各種基於CAS的基礎操作方法,以及各種期望具體同步結構去實現的acquire/release方法。
//基於CAS的基礎操作方法
private final boolean compareAndSetHead(Node update)
private final boolean compareAndSetTail(Node expect,Node update)
private static final boolean compareAndSetWaitStatus(Node node,int expect,int update)
private static final boolean compareAndSetNext(Node node,Node expect,Node update)
//實現的acquire/release方法等等
public final void acquire(int arg)
public final boolean release(int arg)
······
複製程式碼
- 要利用AQS實現一個同步結構,至少要實現兩個基本型別的方法,分別是acquire操作,獲取資源的獨佔權;還有就是release操作,釋放對某個資源的獨佔。