Java併發編程解析 | 基於JDK源碼解析Java領域中併發鎖之ReentrantReadWriteLock鎖的設計思想與實現原理 (二)

蒼穹之邊,浩瀚之摯,眰恦之美; 悟心悟性,善始善終,惟善惟道! —— 朝槿《朝槿兮年說》


寫在開頭

在併發編程領域,有兩大核心問題:一個是互斥,即同一時刻只允許一個線程訪問共享資源;另一個是同步,即線程之間如何通信、協作。
主要原因是,對於多線程實現實現併發,一直以來,多線程都存在2個問題:

  • 線程之間內存共享,需要通過加鎖進行控制,但是加鎖會導致性能下降,同時複雜的加鎖機制也會增加編程編碼難度
  • 過多線程造成線程之間的上下文切換,導致效率低下

因此,在併發編程領域中,一直有一個很重要的設計原則: “ 不要通過內存共享來實現通信,而應該通過通信來實現內存共享。”
簡單來說,就是儘可能通過消息通信,而不是內存共享來實現進程或者線程之間的同步。

關健術語


本文用到的一些關鍵詞語以及常用術語,主要如下:

  • 併發(Concurrent): 在操作系統中,是指一個時間段中有幾個程序都處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行。
  • 並行(Parallel): 當系統有一個以上CPU時,當一個CPU執行一個進程時,另一個CPU可以執行另一個進程,兩個進程互不搶佔CPU資源,可以同時進行。
  • 信號量(Semaphore):  是在多線程環境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被併發調用,也是作系統用來解決併發中的互斥和同步問題的一種方法。
  • 信號量機制(Semaphores): 用來解決同步/互斥的問題的,它是1965年,荷蘭學者 Dijkstra提出了一種卓有成效的實現進程互斥與同步的方法。
  • 管程(Monitor) :  一般是指管理共享變量以及對共享變量的操作過程,讓它們支持併發的一種機制。
  • 互斥(Mutual Exclusion):一個公共資源同一時刻只能被一個進程或線程使用,多個進程或線程不能同時使用公共資源。即就是同一時刻只允許一個線程訪問共享資源的問題。
  • 同步(Synchronization):兩個或兩個以上的進程或線程在運行過程中協同步調,按預定的先後次序運行。即就是線程之間如何通信、協作的問題。
  • 對象池(Object Pool): 指的是一次性創建出 N 個對象,之後所有的線程重複利用這 N 個對象,當然對象在被釋放前,也是不允許其他線程使用的, 一般指保存實例對象的容器。

基本概述

在Java領域中,我們可以將鎖大致分爲基於Java語法層面(關鍵詞)實現的鎖和基於JDK層面實現的鎖。

在Java領域中, 尤其是在併發編程領域,對於多線程併發執行一直有兩大核心問題:同步和互斥。其中:

  • 互斥(Mutual Exclusion):一個公共資源同一時刻只能被一個進程或線程使用,多個進程或線程不能同時使用公共資源。即就是同一時刻只允許一個線程訪問共享資源的問題。
  • 同步(Synchronization):兩個或兩個以上的進程或線程在運行過程中協同步調,按預定的先後次序運行。即就是線程之間如何通信、協作的問題。

針對對於這兩大核心問題,利用管程是能夠解決和實現的,因此可以說,管程是併發編程的萬能鑰匙。
雖然,Java在基於語法層面(synchronized 關鍵字)實現了對管程技術,但是從使用方式和性能上來說,內置鎖(synchronized 關鍵字)的粒度相對過大,不支持超時和中斷等問題。
爲了彌補這些問題,從JDK層面對其“重複造輪子”,在JDK內部對其重新設計和定義,甚至實現了新的特性。
在Java領域中,從JDK源碼分析來看,基於JDK層面實現的鎖大致主要可以分爲以下4種方式:

  • 基於Lock接口實現的鎖:JDK1.5版本提供的ReentrantLock類
  • 基於ReadWriteLock接口實現的鎖:JDK1.5版本提供的ReentrantReadWriteLock類
  • 基於AQS基礎同步器實現的鎖:JDK1.5版本提供的併發相關的同步器Semaphore,CyclicBarrier以及CountDownLatch等
  • 基於自定義API操作實現的鎖:JDK1.8版本中提供的StampedLock類

從閱讀源碼不難發現,在Java SDK 併發包主要通過AbstractQueuedSynchronizer(AQS)實現多線程同步機制的封裝與定義,而通過Lock 和 Condition 兩個接口來實現管程,其中 Lock 用於解決互斥問題,Condition 用於解決同步問題。


一.AQS基礎同步器基本理論

在Java領域中,同步器是專門爲多線程併發設計的同步機制,主要是多線程併發執行時線程之間通過某種共享狀態來實現同步,只有當狀態滿足這種條件時線程才往下執行的一種同步機制。


一個標準的AQS同步器主要有同步狀態機制,等待隊列,條件隊列,獨佔模式,共享模式等五大核心要素組成。
在Java領域中,JDK的JUC(java.util.concurrent.)包中提供了各種併發工具,但是大部分同步工具的實現基於AbstractQueuedSynchronizer類實現,其內部結構主要如下:

  • 同步狀態機制(Synchronization Status):主要用於實現鎖(Lock)機制,是指同步狀態,其要求對於狀態的更新必須原子性的
  • 等待隊列(Wait Queue):主要用於存放等待線程獲取到的鎖資源,並且把線程維護到一個Node(節點)裏面和維護一個非阻塞的CHL Node FIFO(先進先出)隊列,主要是採用自旋鎖+CAS操作來保證節點插入和移除的原子性操作。
  • 條件隊列(Condition Queue):用於實現鎖的條件機制,一般主要是指替換“等待-通知”工作機制,主要是通過ConditionObject對象實現Condition接口提供的方法實現。
  • 獨佔模式(Exclusive Mode):主要用於實現獨佔鎖,主要是基於靜態內部類Node的常量標誌EXCLUSIVE來標識該節點是獨佔模式
  • 共享模式(Shared Mode):主要用於實現共享鎖,主要是基於靜態內部類Node的常量標誌SHARED來標識該節點是共享模式

我們可以得到一個比較通用的併發同步工具基礎模型,大致包含如下幾個內容,其中:

  • 條件變量(Conditional Variable): 利用線程間共享的變量進行同步的一種工作機制
  • 共享變量((Shared Variable)):一般指對象實體對象的成員變量和屬性
  • 阻塞隊列(Blocking Queue):共享變量(Shared Variable)及其對共享變量的操作統一封裝
  • 等待隊列(Wait Queue):每個條件變量都對應有一個等待隊列(Wait Queue),內部需要實現入隊操作(Enqueue)和出隊操作(Dequeue)方法
  • 變量狀態描述機(Synchronization Status):描述條件變量和共享變量之間狀態變化,又可以稱其爲同步狀態
  • 工作模式(Operation Mode): 線程資源具有排他性,因此定義獨佔模式和共享模式兩種工作模式

綜上所述,條件變量和等待隊列的作用是解決線程之間的同步問題;共享變量與阻塞隊列的作用是解決線程之間的互斥問題。

二. JDK顯式鎖統一概念模型

在併發編程領域,有兩大核心問題:一個是互斥,即同一時刻只允許一個線程訪問共享資源;另一個是同步,即線程之間如何通信、協作。

綜合Java領域中的併發鎖的各種實現與應用分析來看,一把鎖或者一種鎖,基本上都會包含以下幾個方面:

  • 鎖的同步器工作機制:主要是考慮共享模式還是獨享模式,是否支持超時機制,以及是否支持超時機制?
  • 鎖的同步器工作模式:主要是基於AQS基礎同步器封裝內部同步器,是否考慮公平/非公平模式?
  • 鎖的狀態變量機制: 主要鎖的狀態設置,是否共享狀態變量?
  • 鎖的隊列封裝定義:主要是指等待隊列和條件隊列,是否需要條件隊列或者等待隊列定義?
  • 鎖的底層實現操作: 主要是指底層CL鎖和CAS操作,是否需要考慮自旋鎖或者CAS操作實例對象方法?
  • 鎖的組合實現新鎖: 主要是基於獨佔鎖和共享鎖,是否考慮對應API自定義操作實現?

綜上所述,大致可以根據上述這些方向,我們便可以清楚🉐️知道Java領域中各種鎖實現的基本理論時和實現思想。


四.ReentrantReadWriteLock(讀寫鎖)的設計與實現

在Java領域中,ReentrantReadWriteLock(讀寫鎖)是針對於Java多線程併發控制中引入一個共享鎖定義讀操作與獨佔鎖定義讀操作等場景共同組合構成一把鎖來提高併發,主要是基於內置的AQS基礎抽象隊列同步器實現的一種併發控制工具類。


通過ReentrantReadWriteLock類能獲取讀鎖和寫鎖,它的讀鎖是可以多線程共享的共享鎖,而它的寫鎖是排他鎖,在被佔時不允許其他線程再搶佔操作。

1. 設計思想


一般來說,在一些特殊的場景中,比如對於數據的讀和寫操作,爲提高併發性能,總會引入共享鎖和獨享鎖來共同組成一把鎖,通常情況下,我們把這類鎖成爲讀寫鎖(ReadWriteLock) 。
簡單來說,就是主要考慮讀和寫操作,讀操作不會修改數據,可以利用多個線程進行讀操作,一般採用共享鎖實現;而寫操作會改變數據本身,只能允許一個線程進行操作,因此採用獨享鎖實現。
讀寫鎖(ReadWriteLock) 最大的一個特點就是在內部維護一對鎖,一把讀鎖(ReadLock) ,一把寫鎖(WriteLock) 。其中,對於線程持有的情況來說,簡單可以總結爲“讀共享,寫獨佔”。

1.1 讀寫鎖的基本理論

雖然讀寫鎖(ReadWriteLock) 之間是有關係的:同一時刻不允許讀鎖和寫鎖同時被搶佔,二者之間是互斥的。
假設現在有N個線程,主要從T(1),T(2),...,一直到T(N)個線程,在讀寫鎖的操作情況如下,其中:

  • 多讀模式(多讀共享):T(N) 個線程可以同時把持並獲取讀鎖,假設T(1)線程成功獲取並持有讀鎖,T(2)線程和後續的T(N)個線程依然可以成功獲取讀鎖,即使T(1)線程沒有釋放持有的讀鎖。
  • 讀寫模式(讀寫互斥):假設T(1)線程成功獲取並持有讀鎖,T(2)線程和後續的T(N)個線程便不能成功獲取且持有寫鎖,除非T(1)線程已經釋放持有的讀鎖。
  • 獨寫模式(單寫獨佔):假設T(1)線程成功獲取並持有寫鎖,T(2)線程和後續的T(N)個線程便不能成功獲取且持有讀鎖和寫鎖,只能等待等待T(1)線程釋放完持有的寫鎖,才能繼續往下執行。

從一定意義上講,根據讀寫鎖操作的情況的性質分析,獲取讀鎖和寫鎖的條件可以大致總結爲:

  • 獲取讀鎖的條件:當前任何線程沒有成功獲取且已經持有寫鎖的情況,纔可能獲取並持有讀鎖。
  • 獲取寫鎖的條件:當前任何線程沒有成功獲取且已經持有寫鎖和讀鎖的情況,纔可能獲取並持有寫鎖。

但是在某些情況下,可能存在某個線程已經獲取並持有讀鎖,希望能夠獲取寫鎖,並且在已經釋放讀鎖時,通常情況下我們稱之爲讀寫鎖的升級。
當然,有升級就會有降級,與之對應的就是讀寫鎖的降級,主要描述的是某個線程已經獲取並持有寫鎖,希望能夠獲取讀鎖,並且已經釋放寫鎖。
一般來說,對於讀寫鎖的升級與降級,我們一般需要注意的以下兩個問題,其中:

  • 讀寫鎖的升級:指的是讀鎖升級爲寫鎖的情況,需要滿足某個線程必須是唯一擁有讀鎖的線程的條件,否則無法升級。
  • 讀寫鎖的降級:指的是寫鎖降級爲讀鎖的情況,沒有什麼條件限制,寫鎖是獨佔鎖,其持有線程是唯一的且不會存在讀鎖持有線程的情況,可以直接平滑升級讀鎖。

1.2 讀寫鎖的實現思想

ReentrantReadWriteLock最早是在JDK1.5版本中提供的,從設計思想上來看,主要包括同步器的工作模式,讀鎖和寫鎖等3個核心要素。其中:

  • 實現ReadWriteLock接口 :主要基於ReadWriteLock接口API實現對應方法,主要是實現writeLock()方法和readLock() 方法,其中writeLock()方法表示獲取寫鎖,readLock() 方法表示獲取讀鎖。
  • 同步器的工作模式:基於AQS基礎抽象隊列同步器封裝內置實現一個靜態的內置同步器抽象類,然後基於這個抽象類分別實現了公平同步器和非公平同步器,用來指定和描述同步器工作模式是公平模式還是非公平模式。
  • 公平/非公平模式:主要描述的是多個線程在同時獲取鎖時是否按照先到先得的順序獲取鎖,如果是則爲公平模式,否則爲非公平模式。
  • 內置兩個靜態公有內部類:定義了讀鎖和寫鎖靜態公有內部類,並且都支持公平/非公平模式,本質都是基於AQS基礎抽象隊列同步器實現。
  • 維護共享狀態變量: 主要是基於一個AQS基礎抽象隊列同步器來實現讀鎖和寫鎖,要求共用一個共享狀態變量。

2. 基本實現

在ReentrantReadWriteLock類在JDK1.8版本中,對於ReentrantReadWriteLock的基本實現如下:

public class ReentrantReadWriteLock
	implements ReadWriteLock, java.io.Serializable {

		private static final long serialVersionUID = -6992448646407690164L;

		/** ReentrantReadWriteLock鎖-內部ReadLock類 */
		private final ReentrantReadWriteLock.ReadLock readerLock;

		/** ReentrantReadWriteLock鎖-內部WriteLock類 */
		private final ReentrantReadWriteLock.WriteLock writerLock;

		/** ReentrantReadWriteLock鎖-內部同步器 */
		final Sync sync; 

		/** ReentrantReadWriteLock鎖-基於AQS封裝內部同步器 */
		abstract static class Sync extends AbstractQueuedSynchronizer {
			private static final long serialVersionUID = 6317671515068378041L;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-begin*/

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-共享狀態移動位數16 */
			static final int SHARED_SHIFT   = 16;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的狀態大小*/
			static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的最大次數*/
			static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-寫鎖的掩碼*/
			static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-本地存儲讀鎖次數*/
			private transient ThreadLocalHoldCounter readHolds;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖的狀態碼值*/
			private transient HoldCounter cachedHoldCounter;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-線程變量*/
			private transient Thread firstReader = null;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-首次讀鎖次數*/
			private transient int firstReaderHoldCount;

			/** ReentrantReadWriteLock鎖-共用狀態變量封裝-end*/

			Sync() {
				readHolds = new ThreadLocalHoldCounter();
				setState(getState()); // ensures visibility of readHolds
			}

			/** ReentrantReadWriteLock鎖-讀鎖標記*/
			abstract boolean readerShouldBlock();

			/** ReentrantReadWriteLock鎖-讀鎖標記*/
			abstract boolean writerShouldBlock();

			//... 其他代碼
		}



		/** ReentrantReadWriteLock鎖-無參數構造(默認非公平模式) */
		public ReentrantReadWriteLock() {
			this(false);
		}

		/** ReentrantReadWriteLock鎖-有參數構造(可選公平/非公平模式) */
		public ReentrantReadWriteLock(boolean fair) {
			sync = fair ? new FairSync() : new NonfairSync();
			readerLock = new ReadLock(this);
			writerLock = new WriteLock(this);
		}

		/** ReentrantReadWriteLock鎖-獲取寫鎖 */
		public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }		
		/** ReentrantReadWriteLock鎖-獲取讀鎖 */
		public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }


		/** ReentrantReadWriteLock鎖-實例化Unsafe支持 */
		private static final sun.misc.Unsafe UNSAFE;

		/** ReentrantReadWriteLock鎖-線程偏移量 */
		private static final long TID_OFFSET;

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		static final long getThreadId(Thread thread) {
			return UNSAFE.getLongVolatile(thread, TID_OFFSET);
		}

		/** ReentrantReadWriteLock鎖-反射機制實例化Unsafe */
		static {
			try {
				UNSAFE = sun.misc.Unsafe.getUnsafe();
				Class<?> tk = Thread.class;
				TID_OFFSET = UNSAFE.objectFieldOffset
					(tk.getDeclaredField("tid"));
			} catch (Exception e) {
				throw new Error(e);
			}
		}
	}
  • 內部同步器:基於AQS基礎同步器封裝和定義了一個靜態內部Sync抽象類
  • 同步器工作模式:提供了 2個構造方法,其中無參數構造方法表示的是默認的工作模式,有參數構造方法主要依據參數來實現指定的工作模式
  • 公平/非公平模式:主要是基於Sync抽象類封裝NonfairSync非公平同步器和封裝NonfairSync非公平同步器來實現。
  • 內置兩個內部類:主要是實現了ReadLock類和WriteLock類,其中ReadLock類對應着讀鎖,WriteLock類對應着寫鎖。

2.1 基於AQS同步器封裝靜態內部Sync抽象類

/** ReentrantReadWriteLock鎖-基於AQS封裝內部同步器 */
abstract static class Sync extends AbstractQueuedSynchronizer {
	private static final long serialVersionUID = 6317671515068378041L;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-begin */

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-共享狀態移動位數16 */
	static final int SHARED_SHIFT   = 16;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的狀態大小*/
	static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的最大次數*/
	static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-寫鎖的掩碼*/
	static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-本地存儲讀鎖次數*/
	private transient ThreadLocalHoldCounter readHolds;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖的狀態碼值*/
	private transient HoldCounter cachedHoldCounter;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-線程變量*/
	private transient Thread firstReader = null;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-首次讀鎖次數*/
	private transient int firstReaderHoldCount;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-end*/

	Sync() {
		readHolds = new ThreadLocalHoldCounter();
		setState(getState()); // ensures visibility of readHolds
	}


	/** ReentrantReadWriteLock鎖-讀鎖標記*/
	abstract boolean readerShouldBlock();

	/** ReentrantReadWriteLock鎖-讀鎖標記*/
	abstract boolean writerShouldBlock();

	/** ReentrantReadWriteLock鎖-獨佔模式獲取讀鎖*/
	protected final boolean tryRelease(int releases) {
		if (!isHeldExclusively())
			throw new IllegalMonitorStateException();
		int nextc = getState() - releases;
		boolean free = exclusiveCount(nextc) == 0;
		if (free)
			setExclusiveOwnerThread(null);
		setState(nextc);
		return free;
	}

	/** ReentrantReadWriteLock鎖-獨佔模式釋放鎖*/
	protected final boolean tryAcquire(int acquires) {

		Thread current = Thread.currentThread();
		int c = getState();
		int w = exclusiveCount(c);
		if (c != 0) {
			// (Note: if c != 0 and w == 0 then shared count != 0)
			if (w == 0 || current != getExclusiveOwnerThread())
				return false;
			if (w + exclusiveCount(acquires) > MAX_COUNT)
				throw new Error("Maximum lock count exceeded");
			// Reentrant acquire
			setState(c + acquires);
			return true;
		}
		if (writerShouldBlock() ||
			!compareAndSetState(c, c + acquires))
			return false;
		setExclusiveOwnerThread(current);
		return true;
	}

	/** ReentrantReadWriteLock鎖-共享模式釋放鎖*/
	protected final boolean tryReleaseShared(int unused) {
		Thread current = Thread.currentThread();
		if (firstReader == current) {
			// assert firstReaderHoldCount > 0;
			if (firstReaderHoldCount == 1)
				firstReader = null;
			else
				firstReaderHoldCount--;
		} else {
			HoldCounter rh = cachedHoldCounter;
			if (rh == null || rh.tid != getThreadId(current))
				rh = readHolds.get();
			int count = rh.count;
			if (count <= 1) {
				readHolds.remove();
				if (count <= 0)
					throw unmatchedUnlockException();
			}
			--rh.count;
		}
		for (;;) {
			int c = getState();
			int nextc = c - SHARED_UNIT;
			if (compareAndSetState(c, nextc))
				return nextc == 0;
		}
	}

	/** ReentrantReadWriteLock鎖-共享模式獲取鎖*/
	protected final int tryAcquireShared(int unused) {

		Thread current = Thread.currentThread();
		int c = getState();
		if (exclusiveCount(c) != 0 &&
			getExclusiveOwnerThread() != current)
			return -1;
		int r = sharedCount(c);
		if (!readerShouldBlock() &&
			r < MAX_COUNT &&
			compareAndSetState(c, c + SHARED_UNIT)) {
			if (r == 0) {
				firstReader = current;
				firstReaderHoldCount = 1;
			} else if (firstReader == current) {
				firstReaderHoldCount++;
			} else {
				HoldCounter rh = cachedHoldCounter;
				if (rh == null || rh.tid != getThreadId(current))
					cachedHoldCounter = rh = readHolds.get();
				else if (rh.count == 0)
					readHolds.set(rh);
				rh.count++;
			}
			return 1;
		}
		return fullTryAcquireShared(current);
	}

	/** ReentrantReadWriteLock鎖-共享模式獲取鎖*/
	final int fullTryAcquireShared(Thread current) {

		HoldCounter rh = null;
		for (;;) {
			int c = getState();
			if (exclusiveCount(c) != 0) {
				if (getExclusiveOwnerThread() != current)
					return -1;
				// else we hold the exclusive lock; blocking here
				// would cause deadlock.
			} else if (readerShouldBlock()) {
				// Make sure we're not acquiring read lock reentrantly
				if (firstReader == current) {
					// assert firstReaderHoldCount > 0;
				} else {
					if (rh == null) {
						rh = cachedHoldCounter;
						if (rh == null || rh.tid != getThreadId(current)) {
							rh = readHolds.get();
							if (rh.count == 0)
								readHolds.remove();
						}
					}
					if (rh.count == 0)
						return -1;
				}
			}
			if (sharedCount(c) == MAX_COUNT)
				throw new Error("Maximum lock count exceeded");
			if (compareAndSetState(c, c + SHARED_UNIT)) {
				if (sharedCount(c) == 0) {
					firstReader = current;
					firstReaderHoldCount = 1;
				} else if (firstReader == current) {
					firstReaderHoldCount++;
				} else {
					if (rh == null)
						rh = cachedHoldCounter;
					if (rh == null || rh.tid != getThreadId(current))
						rh = readHolds.get();
					else if (rh.count == 0)
						readHolds.set(rh);
					rh.count++;
					cachedHoldCounter = rh; // cache for release
				}
				return 1;
			}
		}
	}

	/** ReentrantReadWriteLock鎖-判斷是否獨佔模式*/
	protected final boolean isHeldExclusively() {
		return getExclusiveOwnerThread() == Thread.currentThread();
	}

	// Methods relayed to outer class

	/** ReentrantReadWriteLock鎖-定義條件變量*/
	final ConditionObject newCondition() {
		return new ConditionObject();
	}

	/** ReentrantReadWriteLock鎖-獲取當前鎖的持有者*/
	final Thread getOwner() {
		// Must read state before owner to ensure memory consistency
		return ((exclusiveCount(getState()) == 0) ?
				null :
				getExclusiveOwnerThread());
	}

	/** ReentrantReadWriteLock鎖-獲取讀鎖次數統計*/
	final int getReadLockCount() {
		return sharedCount(getState());
	}

	/** ReentrantReadWriteLock鎖-判斷是否是寫鎖*/
	final boolean isWriteLocked() {
		return exclusiveCount(getState()) != 0;
	}

	/** ReentrantReadWriteLock鎖-獲取寫鎖持有次數統計*/
	final int getWriteHoldCount() {
		return isHeldExclusively() ? exclusiveCount(getState()) : 0;
	}

	/** ReentrantReadWriteLock鎖-獲取讀鎖次持有數統計*/
	final int getReadHoldCount() {
		if (getReadLockCount() == 0)
			return 0;

		Thread current = Thread.currentThread();
		if (firstReader == current)
			return firstReaderHoldCount;

		HoldCounter rh = cachedHoldCounter;
		if (rh != null && rh.tid == getThreadId(current))
			return rh.count;

		int count = readHolds.get().count;
		if (count == 0) readHolds.remove();
		return count;
	}

	/** ReentrantReadWriteLock鎖-獲取讀鎖*/
	final boolean tryReadLock() {
		Thread current = Thread.currentThread();
		for (;;) {
			int c = getState();
			if (exclusiveCount(c) != 0 &&
				getExclusiveOwnerThread() != current)
				return false;
			int r = sharedCount(c);
			if (r == MAX_COUNT)
				throw new Error("Maximum lock count exceeded");
			if (compareAndSetState(c, c + SHARED_UNIT)) {
				if (r == 0) {
					firstReader = current;
					firstReaderHoldCount = 1;
				} else if (firstReader == current) {
					firstReaderHoldCount++;
				} else {
					HoldCounter rh = cachedHoldCounter;
					if (rh == null || rh.tid != getThreadId(current))
						cachedHoldCounter = rh = readHolds.get();
					else if (rh.count == 0)
						readHolds.set(rh);
					rh.count++;
				}
				return true;
			}
		}
	}

	/** ReentrantReadWriteLock鎖-獲取寫鎖*/
	final boolean tryWriteLock() {
		Thread current = Thread.currentThread();
		int c = getState();
		if (c != 0) {
			int w = exclusiveCount(c);
			if (w == 0 || current != getExclusiveOwnerThread())
				return false;
			if (w == MAX_COUNT)
				throw new Error("Maximum lock count exceeded");
		}
		if (!compareAndSetState(c, c + 1))
			return false;
		setExclusiveOwnerThread(current);
		return true;
	}

	/** ReentrantReadWriteLock鎖-流處理*/
	private void readObject(java.io.ObjectInputStream s)
	throws java.io.IOException, ClassNotFoundException {
		s.defaultReadObject();
		readHolds = new ThreadLocalHoldCounter();
		setState(0); // reset to unlocked state
	}

	/** ReentrantReadWriteLock鎖-獲取狀態*/
	final int getCount() { return getState(); }

}
  • 實現方式: 主要是基於AQS基礎同步器來實現,其中封裝抽象了readerShouldBlock()方法和writerShouldBlock()方法,用於標記當前請求的線程是獲取什麼類型的鎖。其中:
    • readerShouldBlock()方法:依據標記返回的是true,標記線程獲取的是ReadLock鎖
    • writerShouldBlock()方法:依據標記返回的是true,標記線程獲取的是WriteLock鎖
  • 維護共用狀態變量: 對於共享狀態變量的實現,主要是在內部的同步器中Sync類中定義HoldCounter類和ThreadLocalHoldCounter類實現的,其中定義了一堆常量,統計讀寫鎖狀態值的sharedCount()方法和exclusiveCount()方法。
  • 讀寫鎖的主要方法: 主要是提供了tryReadLock()方法和tryWriteLock()方法,其中:
    • tryReadLock()方法:獲取讀鎖方法,核心處理是自旋+compareAndSetState()方法來處理
    • tryWriteLock()方法:獲取寫鎖方法,核心處理是通過compareAndSetState()方法來處理
  • 讀寫鎖的獲取方式:基於AQS基礎同步器來實現對於共享模式和獨享模式兩種情況,都提供了對應的方法。其中:
    • tryAcquire()方法:獨享模式獲取鎖方法,這裏主要針對WriteLock鎖,核心處理是通過AQS基礎同步器中compareAndSetState()方法來處理,實現狀態變量的操作
    • tryAcquireShared() 方法:共享模式獲取鎖方法,這裏主要對應ReadLock鎖,核心處理是通過AQS基礎同步器中compareAndSetState()方法來處理,實現狀態變量的操作
  • 讀寫鎖的釋放方式:基於AQS基礎同步器來實現對於共享模式和獨享模式兩種情況,都提供了對應的方法。其中:
    • tryRelease(int releases) 方法:獨享模式釋放鎖方法
    • tryReleaseShared(int unused) 方法:共享模式釋放鎖方法,核心處理是自旋+compareAndSetState()方法來處理
  • 其他方法:主要還提供了一些比較常規的方法,其中:
    • getCount() 方法:主要是基於AQS基礎同步器來獲取狀態變量
    • getOwner()方法:主要是用於獲取當前鎖的持有者,一般是線程對象,根據_exclusiveCount_(getState()) == 0來判斷,條件成立就默認爲null; 否則,通過AQS基礎同步器中的getExclusiveOwnerThread()方法來獲取。
    • getReadLockCount() 方法:用於獲取某個線程對於ReadLock鎖的數量,主要是統計次數
    • isWriteLocked() 方法:用於判斷線程是否已經獲取並持有WriteLock鎖
    • getWriteHoldCount()方法:用於獲取線程對於WriteLock鎖的持有情況,主要是統計次數
    • getReadHoldCount() 方法:用於獲取線程對於WriteLock鎖的持有情況,主要是統計次數
    • isHeldExclusively() 方法:用於判斷是否獨佔模式
    • unmatchedUnlockException()方法:封裝一個異常處理信息,主要是指定IllegalMonitorStateException

2.2 基於Sync抽象類封裝共享狀態變量

/** ReentrantReadWriteLock鎖-基於AQS封裝內部同步器 */
abstract static class Sync extends AbstractQueuedSynchronizer {
	private static final long serialVersionUID = 6317671515068378041L;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-begin*/
	
	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-共享狀態移動位數16 */
	static final int SHARED_SHIFT   = 16;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的狀態大小*/
	static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖每次加鎖的最大次數*/
	static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-寫鎖的掩碼*/
	static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-本地存儲讀鎖次數*/
	private transient ThreadLocalHoldCounter readHolds;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖的狀態碼值*/
	private transient HoldCounter cachedHoldCounter;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-線程變量*/
	private transient Thread firstReader = null;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-首次讀鎖次數*/
	private transient int firstReaderHoldCount;

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-end*/
	
	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-構造方法*/
	Sync() {
		readHolds = new ThreadLocalHoldCounter();
		setState(getState()); // ensures visibility of readHolds
	}


	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-讀鎖的狀態碼值*/
	static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }

	/** ReentrantReadWriteLock鎖-共用狀態變量封裝-寫鎖的狀態碼值*/
	static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

	/** ReentrantReadWriteLock鎖-共用狀態變量-統計計數器 */
	static final class HoldCounter {
		int count = 0;
		// Use id, not reference, to avoid garbage retention
		final long tid = getThreadId(Thread.currentThread());
	}

	/** ReentrantReadWriteLock鎖-共用狀態變量-本地存儲統計副本 */
	static final class ThreadLocalHoldCounter
		extends ThreadLocal<HoldCounter> {
			public HoldCounter initialValue() {
				return new HoldCounter();
			}
		}
	//... 其他代碼

}
  • 實現方式: 主要是在內部的同步器中Sync類中定義HoldCounter類和ThreadLocalHoldCounter類實現的。其中:
    • HoldCounter類:主要是定義了一個計數器count和一個線程編號tid變量,其中計數器count默認值爲0,而線程編號tid通過_getThreadId_(Thread.currentThread())方法來獲取。
    • ThreadLocalHoldCounter類:基於ThreadLocal和HoldCounter來提供了initialValue()方法,主要是實例話化HoldCounter類。
  • 共用狀態常量:主要是在內部的同步器中Sync類中定義了相關常量,其中:
    • SHARED_SHIFT: 主要用於標記位移的位數,默認採用 整型16位
    • SHARED_UNIT:表示讀鎖加鎖操作時每次對應的狀態值大小,將1左移動16位正好對應高16位的1.
    • MAX_COUNT:表示讀鎖能執行加鎖操作的最大次數,一般爲16個二進制的1
    • EXCLUSIVE_MASK:寫鎖的掩碼,一般爲16個二進制的1
  • 主要方法:主要提供了統計讀寫鎖狀態值的sharedCount()方法和exclusiveCount()方法,其中:
    • sharedCount()方法:獲取讀鎖的狀態碼值,根據目標參數(targetParam)左移16位即可得到
    • exclusiveCount()方法:獲取寫鎖的狀態碼值,根據目標參數(targetParam)同寫鎖的掩碼做邏輯與(&)運算便可得到。

一般來說,AQS基礎同步器的共享狀態變量是整型的32位,要基於一個AQS基礎同步器實現讀寫鎖的共享一個共享變量。
其中,最公平的方式設計方式就是讀鎖與寫鎖各自佔用16位,就意味着讀鎖佔用的是高16位,寫鎖佔用的是低16位的。

但是,在獲取讀寫鎖的狀態值的時候,還會涉及一些額外的計算,這樣的設計方式可能會需要用到位移和邏輯與操作等。

2.3 基於Sync抽象類封裝FairSync公平同步器

/** ReentrantReadWriteLock鎖-基於Sync抽象類封裝FairSync公平同步器 */
static final class FairSync extends Sync {

	private static final long serialVersionUID = -2274990926593161451L;

	/** ReentrantReadWriteLock鎖- 實現writerShouldBlock方法*/
	final boolean writerShouldBlock() {
		return hasQueuedPredecessors();
	}

	/** ReentrantReadWriteLock鎖- 實現readerShouldBlock方法*/
	final boolean readerShouldBlock() {
		return hasQueuedPredecessors();
	}
}
  • 實現方式:基於Sync抽象類封裝FairSync公平同步器,表示支持公平模式
  • 主要方法:主要實現實現writerShouldBlock()方法和readerShouldBlock()方法,其中:
    • writerShouldBlock()方法:通過hasQueuedPredecessors()實現
    • readerShouldBlock()方法:通過apparentlyFirstQueuedIsExclusive()實現

2.4 基於Sync抽象類封裝NonfairSync非公平同步器


/** ReentrantReadWriteLock鎖-基於Sync抽象類封裝FairSync公平同步器 */
static final class NonfairSync extends Sync {
	
	private static final long serialVersionUID = -8159625535654395037L;
	
	/** ReentrantReadWriteLock鎖- 實現writerShouldBlock方法*/
	final boolean writerShouldBlock() {
		return false; // writers can always barge
	}

	/** ReentrantReadWriteLock鎖- 實現readerShouldBlock方法*/
	final boolean readerShouldBlock() {
		return apparentlyFirstQueuedIsExclusive();
	}
}

  • 實現方式:基於Sync抽象類封裝NonfairSync非公平同步器,表示支持非公平模式
  • 主要方法:主要實現實現writerShouldBlock()方法和readerShouldBlock()方法,其中:
    • writerShouldBlock()方法:默認返回false
    • readerShouldBlock()方法:通過apparentlyFirstQueuedIsExclusive()實現

2.5 基於Lock接口實現ReadLock讀鎖內部類

/** ReentrantReadWriteLock鎖-基於Lock接口實現ReadLock讀鎖內部類*/
public static class ReadLock implements Lock, java.io.Serializable {
	private static final long serialVersionUID = -5992448646407690164L;

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-同步器 */
	private final Sync sync;

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-內部構造方法*/
	protected ReadLock(ReentrantReadWriteLock lock) {
		sync = lock.sync;
	}

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-獲取鎖方法(默認共享模式)*/
	public void lock() {
		sync.acquireShared(1);
	}

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-獲取鎖方法(支持中斷機制)*/
	public void lockInterruptibly() throws InterruptedException {
		sync.acquireSharedInterruptibly(1);
	}

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-嘗試獲取鎖(一般模式)*/
	public boolean tryLock() {
		return sync.tryReadLock();
	}


	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-嘗試獲取鎖(支持超時機制)*/
	public boolean tryLock(long timeout, TimeUnit unit)
	throws InterruptedException {
		return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
	}

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-釋放鎖*/
	public void unlock() {
		sync.releaseShared(1);
	}

	/** ReentrantReadWriteLock鎖-ReadLock讀鎖內部類-條件變量*/
	public Condition newCondition() {
		throw new UnsupportedOperationException();
	}


	public String toString() {
		int r = sync.getReadLockCount();
		return super.toString() +
			"[Read locks = " + r + "]";
	}
}
  • 實現方式:主要是基於Lock接口來實現的ReadLock鎖,同時通過構造方法指定了一個內部同步器Sync,其對應的方法都是基於AQS基礎同步器的共享模式來實現的。
  • 獲取鎖方式:主要提供了4個方法來實現鎖的獲取,其中:
    • 無參數的lock()方法: 獲取鎖的一般模式,主要是基於AQS基礎同步器中的acquireShared(int arg)方法來實現,其核心處理邏輯是doAcquireShared(int arg)方法
    • 無參數的lockInterruptibly()方法:獲取可中斷鎖的模式,主要是基於AQS基礎同步器中的acquireSharedInterruptibly(int arg)方法來實現,其核心處理邏輯是doAcquireSharedInterruptibly(int arg)方法
    • 無參數的tryLock()方法:嘗試獲取ReadLock鎖,主要是基於AQS基礎同步器中的tryReadLock()方法來實現,其核心處理邏輯是自旋+compareAndSetState()方法的加持CAS操作的。
    • 有參數的ryLock()方法:嘗試獲取ReadLock鎖,支持超時機制,主要是基於AQS基礎同步器中的tryAcquireSharedNanos(int arg, long nanosTimeout)方法來實現,其核心處理邏輯是在doAcquireSharedNanos(int arg, long nanosTimeout)方法,主要是自旋+shouldParkAfterFailedAcquire()方法的加持CAS操作的。
  • 釋放鎖方式:主要提供了一個unlock()方法來實現ReadLock 的釋放,其中本質是基於AQS基礎同步器中的releaseShared(int arg) 方法,其中核心處理邏輯是doReleaseShared()的方法,其核心處理是自旋+compareAndSetWaitStatus()方法來加持CAS操作的。

2.6 基於Lock接口實現WriteLock寫鎖內部類

/** ReentrantReadWriteLock鎖-基於Lock接口實現WriteLock寫鎖內部類*/
public static class WriteLock implements Lock, java.io.Serializable {
	private static final long serialVersionUID = -4992448646407690164L;

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-同步器*/
	private final Sync sync;

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-內部構造方法*/
	protected WriteLock(ReentrantReadWriteLock lock) {
		sync = lock.sync;
	}

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-獲取鎖方法(獨佔模式)*/
	public void lock() {
		sync.acquire(1);
	}


	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-獲取鎖方法(可中斷)*/
	public void lockInterruptibly() throws InterruptedException {
		sync.acquireInterruptibly(1);
	}

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-獲取鎖方法(一般模式)*/
	public boolean tryLock( ) {
		return sync.tryWriteLock();
	}

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-獲取鎖方法(支持超時機制)*/
	public boolean tryLock(long timeout, TimeUnit unit)
	throws InterruptedException {
		return sync.tryAcquireNanos(1, unit.toNanos(timeout));
	}


	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-釋放鎖*/
	public void unlock() {
		sync.release(1);
	}



	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-條件變量*/
	public Condition newCondition() {
		return sync.newCondition();
	}


	public String toString() {
		Thread o = sync.getOwner();
		return super.toString() + ((o == null) ?
								   "[Unlocked]" :
								   "[Locked by thread " + o.getName() + "]");
	}

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-是否獨佔判斷*/
	public boolean isHeldByCurrentThread() {
		return sync.isHeldExclusively();
	}

	/** ReentrantReadWriteLock鎖-WriteLock寫鎖內部類-統計數量*/
	public int getHoldCount() {
		return sync.getWriteHoldCount();
	}
}
  • 實現方式:主要是基於Lock接口來實現的WriteLock鎖,同時通過構造方法指定了一個內部同步器Sync,其對應的方法都是基於AQS基礎同步器的獨佔模式來實現的。
  • 獲取鎖式:主要提供了4個方法來實現鎖的獲取,其中:
    • 無參數的lock()方法: 獲取WriteLock鎖的一般模式,主要是基於AQS基礎同步器中的acquire(int arg)方法來實現,其核心處理邏輯是acquireQueued(final Node node, int arg)方法
    • 無參數的lockInterruptibly()方法:獲取WriteLock鎖可中斷鎖的模式,主要是基於AQS基礎同步器中的acquireInterruptibly(int arg)方法來實現,其核心處理邏輯是doAcquireInterruptibly(int arg)方法
    • 無參數的tryLock()方法:嘗試獲取WriteLock鎖,主要是基於AQS基礎同步器中的tryReadLock()方法來實現,其核心處理邏輯是自旋+compareAndSetState()方法的加持CAS操作的。
    • 有參數的ryLock()方法:嘗試獲取WriteLock鎖,支持超時機制,主要是基於AQS基礎同步器中的tryAcquireNanos(int arg, long nanosTimeout)方法來實現,其核心處理邏輯是在doAcquireNanos(int arg, long nanosTimeout)方法,主要是自旋+shouldParkAfterFailedAcquire()方法的加持CAS操作的。
  • 釋放鎖方式:主要提供了一個unlock()方法來實現ReadLock 的釋放,其中本質是基於AQS基礎同步器中unparkSuccessor(Node node)方法,主要是通過_compareAndSetWaitStatus_()方法來加持CAS操作的。

3. 具體實現

public class ReentrantReadWriteLock
	implements ReadWriteLock, java.io.Serializable {

		private static final long serialVersionUID = -6992448646407690164L;

		/** ReentrantReadWriteLock鎖-內部ReadLock類 */
		private final ReentrantReadWriteLock.ReadLock readerLock;

		/** ReentrantReadWriteLock鎖-內部WriteLock類 */
		private final ReentrantReadWriteLock.WriteLock writerLock;

		/** ReentrantReadWriteLock鎖-內部同步器 */
		final Sync sync; 

		/** ReentrantReadWriteLock鎖-實例化Unsafe支持 */
		private static final sun.misc.Unsafe UNSAFE;

		/** ReentrantReadWriteLock鎖-線程偏移量 */
		private static final long TID_OFFSET;

		/** ReentrantReadWriteLock鎖-基於AQS封裝內部同步器 */
		abstract static class Sync extends AbstractQueuedSynchronizer {
			private static final long serialVersionUID = 6317671515068378041L;

			static final int SHARED_SHIFT   = 16;

			static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

			static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

			static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

			private transient ThreadLocalHoldCounter readHolds;

			private transient HoldCounter cachedHoldCounter;

			private transient Thread firstReader = null;
			private transient int firstReaderHoldCount;

			Sync() {
				readHolds = new ThreadLocalHoldCounter();
				setState(getState()); // ensures visibility of readHolds
			}
			abstract boolean readerShouldBlock();

			abstract boolean writerShouldBlock();

			//... 其他代碼
		}



		/** ReentrantReadWriteLock鎖-無參數構造(默認非公平模式) */
		public ReentrantReadWriteLock() {
			this(false);
		}

		/** ReentrantReadWriteLock鎖-有參數構造(可選公平/非公平模式) */
		public ReentrantReadWriteLock(boolean fair) {
			sync = fair ? new FairSync() : new NonfairSync();
			readerLock = new ReadLock(this);
			writerLock = new WriteLock(this);
		}

		/** ReentrantReadWriteLock鎖-獲取寫鎖 */
		public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }		
		/** ReentrantReadWriteLock鎖-獲取讀鎖 */
		public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public final boolean isFair() {
			return sync instanceof FairSync;
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		protected Thread getOwner() {
			return sync.getOwner();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public int getReadLockCount() {
			return sync.getReadLockCount();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public boolean isWriteLocked() {
			return sync.isWriteLocked();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public boolean isWriteLockedByCurrentThread() {
			return sync.isHeldExclusively();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public int getWriteHoldCount() {
			return sync.getWriteHoldCount();
		}
		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public int getReadHoldCount() {
			return sync.getReadHoldCount();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		protected Collection<Thread> getQueuedWriterThreads() {
			return sync.getExclusiveQueuedThreads();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		protected Collection<Thread> getQueuedReaderThreads() {
			return sync.getSharedQueuedThreads();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public final boolean hasQueuedThreads() {
			return sync.hasQueuedThreads();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public final boolean hasQueuedThread(Thread thread) {
			return sync.isQueued(thread);
		}
		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public final int getQueueLength() {
			return sync.getQueueLength();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		protected Collection<Thread> getQueuedThreads() {
			return sync.getQueuedThreads();
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public boolean hasWaiters(Condition condition) {
			if (condition == null)
				throw new NullPointerException();
			if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
				throw new IllegalArgumentException("not owner");
			return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		protected Collection<Thread> getWaitingThreads(Condition condition) {
			if (condition == null)
				throw new NullPointerException();
			if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
				throw new IllegalArgumentException("not owner");
			return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		public int getWaitQueueLength(Condition condition) {
			if (condition == null)
				throw new NullPointerException();
			if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
				throw new IllegalArgumentException("not owner");
			return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
		}

		/** ReentrantReadWriteLock鎖-獲取線程變量 */
		static final long getThreadId(Thread thread) {
			return UNSAFE.getLongVolatile(thread, TID_OFFSET);
		}

		/** ReentrantReadWriteLock鎖-反射機制實例化Unsafe */
		static {
			try {
				UNSAFE = sun.misc.Unsafe.getUnsafe();
				Class<?> tk = Thread.class;
				TID_OFFSET = UNSAFE.objectFieldOffset
					(tk.getDeclaredField("tid"));
			} catch (Exception e) {
				throw new Error(e);
			}
		}
	}
  • 讀寫鎖同步器:主要提供了2個構造方法來實現讀寫鎖的管理,其中:
    • 無參數構造方法:默認非公平模式,主要是通過this關鍵字來指定的
    • 有參數構造方法:可選公平/非公平模式,依據指定傳入公平標記fair來實例化NonfairSync非公平同步器和FairSync公平同步器,其中,當fair=true時,是公平平模式;否則,當fair=false時爲非公平模式。同時,實例化ReadLock和WriteLock對象。
  • 讀鎖主要方法:對於讀鎖的操作,一般我們只需要關注readLock()方法和類似getReadXX() 方法,其中:
    • readLock()方法:主要用於獲取和實現讀鎖ReadLock
    • getReadHoldCount() 方法:主要用於統計某個線程對於讀鎖的持有情況
    • getReadLockCount() 方法:主要用於統計某個線程對於讀鎖的獲取的次數
  • 寫鎖主要方法:對於讀鎖的操作,一般我們只需要關注readLock()方法和類似包含xWriteXX() 方法,其中:
    • writeLock() 方法:主要用於獲取和實現寫鎖WriteLock
    • getWriteHoldCount()方法:主要用於統計當前線程對於寫鎖WriteLock的持有情況
    • isWriteLocked()方法:主要用於判斷某個線程對於寫鎖WriteLock的是否加鎖
    • isWriteLockedByCurrentThread() 方法:主要用於判斷當前線程對於寫鎖WriteLock的是否加鎖
  • 條件隊列操作方法:還提供了一系列的對於條件變量隊列操作方法,其中:
    • getQueuedWriterThreads() 方法:主要用於獲取線程等待獲取寫鎖WriteLock的情況
    • getQueuedReaderThreads() 方法:主要用於獲取線程等待獲取讀鎖ReadLock的情況
    • getQueuedThreads()方法:主要用於獲取線程等待獲取讀鎖ReadLock和寫鎖WriteLock的情況
    • getQueueLength() 方法:主要用於獲取線程等待獲取讀鎖ReadLock和寫鎖WriteLock的個數
  • 等待隊列操作方法: 還提供了一系列的對於等待隊列操作方法,其中:
    • getWaitingThreads() 方法:主要依據Condition來用於獲取等待隊列中所有的線程的對象
    • getWaitQueueLength() 方法:主要依據Condition來用於獲取等待隊列中所有的線程對於寫鎖WriteLock的相關的個數
  • 其他方法:除此之外,還提供了一些隊列操作的常規方法,其中:
    • hasQueuedThread() 方法:主要依據單個Thread對象用於獲取線程是否有獲取讀鎖ReadLock和寫鎖WriteLock的情況
    • hasQueuedThreads() 方法:主要用於獲取多個線程是否有獲取讀鎖ReadLock和寫鎖WriteLock的情況
    • hasWaiters()方法:主要依據Condition來用於判斷等待隊列中所有的線程對於寫鎖WriteLock的相關情況
    • isFair() 方法:用於判斷是否公平模式
    • getThreadId()方法:獲取線程編號ID,主要是通過指定_UNSAFE_.getLongVolatile(thread, TID_OFFSET)實現。


綜上所述,ReentrantReadWriteLock鎖是基於AQS基礎同步器的共享模式和獨享模式共同孵化的產物,支持公平/非公平模式,其中的ReadLock和WriteLock是基於同一個AQS基礎同步器來實現,維護了共用狀態變量機制。

寫在最後

通過對Java領域中,JDK內部提供的各種鎖的實現來看,一直圍繞的核心主要還是基於AQS基礎同步器來實現的,但是AQS基礎同步器不是一種非它不可的技術標準規範,更多的只是一套技術參考指南。

但是,實際上,Java對於鎖的實現與運用遠遠不止這些,還有相位器(Phaser)和交換器(Exchanger),以及在Java JDK1.8版本之前併發容器ConcurrentHashMap中使用的分段鎖(Segment)。

不論是何種實現和應用,在Java併發編程領域來講,都是圍繞線程安全問題的角度去考慮的,只是針對於各種各樣的業務場景做的具體的實現。

一定意義上來講,對線程加鎖只是併發編程的實現方式之一,相對於實際應用來說,Java領域中的鎖都只是一種單一應用的鎖,只是給我們掌握Java併發編程提供一種思想沒,三言兩語也不可能詳盡。

到此爲止,這算是對於Java領域中併發鎖的最終章,文中表述均爲個人看法和個人理解,如有不到之處,忘請諒解也請給予批評指正。

最後,技術研究之路任重而道遠,願我們熬的每一個通宵,都撐得起我們想在這條路上走下去的勇氣,未來仍然可期,與各位程序編程君共勉!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章