併發編程(六):AQS之讀寫鎖ReentrantReadWriteLock

一,AQS源碼博文:併發編程:AbstractQueuedSynchronizer源碼分析

二,ReentrantReadWriteLock讀寫鎖介紹

1,讀寫鎖介紹

     ReentrantReadWriteLock 雖然與 ReentrantLock 沒有直接關係,但是在功能上算是對 ReentrantLock 的擴展。在 ReentrantLock 重入獨佔鎖的功能上,添加了共享鎖的擴展,分別對應 ReentrantReadWriteLock 的寫鎖(WriteLock)和讀鎖(ReadLock)。ReentrantReadWriteLock 內部定義 Sync 類繼承自 AQS 對加鎖方式進行擴展,在讀鎖寫鎖獲取以及讀寫鎖交叉獲取提供了自身機制,以此保證線程同步。ReentrantReadWriteLock 在加鎖過程中,對 Integer 的32位進行分割,以高16位表示共享鎖,以低16位表示獨佔鎖。在進行加鎖時,通過左移右移以及與運算判斷當前加鎖狀態及重入狀態,並進線程進行調度。

2,類圖

    * ReentrantReadWriteLock 實現自 ReadWriteLock 接口,並在內部定義了鎖實現了相關內部類。

    * SyncFairSyncNonfairSync 三個內部類是對 AQS 的層次擴展,用來擴展加鎖的一系列邏輯處理

    * WriteLockReadLock 兩個內部類實現自 Lock 接口,並通過 ReentrantReadWriteLock  創建後對外提供,在應用層進行不同的加鎖處理

3,常用API

// 創建讀寫鎖, 通過參數指定公平鎖/非公平鎖
public ReentrantReadWriteLock();
public ReentrantReadWriteLock(boolean fair);
// 創建讀鎖
public ReentrantReadWriteLock.ReadLock  readLock()
// 創建寫鎖
public ReentrantReadWriteLock.WriteLock writeLock();
// 嘗試加鎖
public boolean tryLock();
public boolean tryLock(long timeout, TimeUnit unit);
// 加鎖
public void lock();
public void lockInterruptibly() throws InterruptedException;
// 釋放鎖
public void unlock();

    * 在上述API中,關於鎖操作的一些API,都存在讀鎖和寫鎖的區別;其中,在讀鎖和寫鎖的處理中,又存在公平鎖和非公平鎖的區分;

    * 後續源碼分析中,讀鎖和寫鎖會分別分析,但是公平鎖和分公平鎖只對非公平鎖進行分析,公平鎖參考重入鎖

4,ReentrantReadWriteLock 加鎖分析

4.1,整體鎖狀態存儲

    * ReentrantReadWriteLock 在鎖狀態存儲中,對 Integer 32位進行拆分,使用高16位存儲共享鎖,使用低16位存儲獨佔鎖。所以無論是共享鎖的共享次數還是獨佔鎖的重入次數,最高爲((1 << 16) - 1)。

// 1 << 16就是1在二進制情況下右移16位結果爲
10000 0000 0000 0000 = 2^16 = 65536
// (1 << 16) - 1也是在二進制下進行減操作
1111 1111 1111 1111 = 2^16 - 1 = 65535

    * ReentrantReadWriteLock 在獨佔鎖加鎖時,是對低16位進行加1,在獲取獨佔鎖的重入次數時,也是對低16位進行與運算以獲取結果加鎖具體看代碼框

// 獨佔鎖state遞增
compareAndSetState(c, c + 1)
// 獨佔鎖獲取重入次數
// EXCLUSIVE_MASK:常量,最終結果爲 (1111 1111 1111 1111),也就是對應 Integer 的低16位
// 用c和 EXCLUSIVE_MASK 進行與運算,也就是用c的低16位和 EXCLUSIVE_MASK 進行與運算,
// 與運算同1爲1,其餘爲0,所以獲取到的結果就是c的低16位表示的數字,然後再默認轉換10進制,即爲重入數量
static int exclusiveCount(int c) { 
	return c & EXCLUSIVE_MASK; 
}
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
static final int SHARED_SHIFT   = 16;

// 比如,此時共享爲3次,重入爲0次,則c的二進制表示爲
0000 0000 0000 0011 0000 0000 0000 0000
// EXCLUSIVE_MASK的二進制表示爲
0000 0000 0000 0000 1111 1111 1111 1111
// 運算結果
	0000 0000 0000 0011 0000 0000 0000 0000
&	0000 0000 0000 0000 1111 1111 1111 1111
-------------------------------------------
	0000 0000 0000 0000 0000 0000 0000 0000 = 0
	
// 所以此時獲取到的獨佔鎖數量爲0
// 假設可以獲取成功,則對獨佔鎖遞增,通過CAS,用c + 1代替 c,此時,c的二進制表示爲:
0000 0000 0000 0011 0000 0000 0000 0001
// 這時候繼續計算,獲取獨佔鎖的次數,運算如下
	0000 0000 0000 0011 0000 0000 0000 0001
&	0000 0000 0000 0000 1111 1111 1111 1111
-------------------------------------------
	0000 0000 0000 0000 0000 0000 0000 0001 = 1

    * 同樣,ReentrantReadWriteLock 在對共享鎖加鎖時,是對高16位進行加鎖,在獲取共享鎖次數時,先對 state 無符號右移16位,然後直接獲取結果,具體過程如代碼框

// 加鎖成功後,c遞增,按照重入邏輯,遞增應該爲1
// 而此時遞增了(1 << SHARED_SHIFT),也就是二進制下 1 0000 0000 0000 0000
// 除去低16位,也就是剛好在高16位上遞增1
compareAndSetState(c, c + SHARED_UNIT)
static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
static final int SHARED_SHIFT   = 16;

// 共享鎖獲取鎖重入次數
// 直接將state無符號右移16位,表示的就是共享鎖的重入次數
// 而右移去掉的16位,也就剛好是獨佔鎖表示的低16位
static int sharedCount(int c)    { 
	return c >>> SHARED_SHIFT; 
}
static final int SHARED_SHIFT   = 16;

// 繼續舉例,比如此時共享次數3,獨佔次數爲3,則state的二進制表示爲
0000 0000 0000 0011 0000 0000 0000 0011
// 無符號右移16位後,高位補0,值如下
0000 0000 0000 0000 0000 0000 0000 0011 = 3

// 假設此時共享鎖獲取成功,state加上(1 << SHARED_SHIFT),如下
	0000 0000 0000 0011 0000 0000 0000 0011
+	0000 0000 0000 0001 0000 0000 0000 0000
-------------------------------------------
	0000 0000 0000 0100 0000 0000 0000 0000
// 此時繼續獲取數量,對state無符號右移16位,結果如下
0000 0000 0000 0000 0000 0000 0000 0100 = 4

5,功能DEMO

package com.gupao.concurrent;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author pj_zhang
 * @create 2019-10-19 12:37
 **/
public class ReadAndWriteLockTest {

    private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();

    private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();

    private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

    public static void main(String[] args) throws InterruptedException {
        testReadAndWriteLock();
    }

    public static void testWriteAndReadLock() throws InterruptedException {
        new Thread(() -> {
            System.out.println("開始獲取鎖。。。");
            // 先獲取寫鎖後獲取讀鎖
            // 讀鎖會順利獲取
            writeLock.lock();
            System.out.println("獲取寫鎖成功。。。");
            readLock.lock();
            System.out.println("獲取讀鎖成功。。。");
            writeLock.unlock();
            System.out.println("釋放讀鎖成功。。。");
            readLock.unlock();
            System.out.println("釋放寫鎖成功");
        }, "READ_AND_WRITE").start();
    }

    public static void testReadAndWriteLock() throws InterruptedException {
        new Thread(() -> {
            System.out.println("開始獲取鎖。。。");
            // 先獲取讀寫再獲取寫鎖
            // 此時已經存在鎖,則獨佔鎖獲取失敗
            readLock.lock();
            System.out.println("獲取讀鎖成功。。。");
            writeLock.lock();
            System.out.println("獲取寫鎖成功。。。");
            writeLock.unlock();
            System.out.println("釋放讀鎖成功。。。");
            readLock.unlock();
            System.out.println("釋放寫鎖成功");
        }, "READ_AND_WRITE").start();
    }

    /**
     * 不同線程測試讀寫鎖
     *
     * @throws InterruptedException
     */
    public static void testLockWithDiffThread() throws InterruptedException {
        // 先啓動一個讀鎖
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "加讀鎖前執行。。。, time: " + System.currentTimeMillis());
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "加讀鎖後執行。。。, time: " + System.currentTimeMillis());
            sleep(1000);
            readLock.unlock();
        }, "READ_1").start();
        Thread.sleep(10);
        // 再一個一個讀鎖,模擬讀鎖不阻塞
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "加讀鎖前執行。。。, time: " + System.currentTimeMillis());
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "加讀鎖後執行。。。, time: " + System.currentTimeMillis());
            sleep(1000);
            readLock.unlock();
        }, "READ_2").start();
        Thread.sleep(10);
        // 啓動一個寫鎖,模擬寫鎖阻塞
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "_加寫鎖前執行。。。, time: " + System.currentTimeMillis());
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + "_加寫鎖後執行。。。, time: " + System.currentTimeMillis());
            sleep(1000);
            writeLock.unlock();
        }, "WRITE").start();
        Thread.sleep(10);
        // 自啓動一個讀鎖,模擬共享鎖執行時,阻塞一個寫鎖,之後再獲取讀鎖,在寫鎖後執行
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "加讀鎖前執行。。。, time: " + System.currentTimeMillis());
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "加讀鎖後執行。。。, time: " + System.currentTimeMillis());
            sleep(1000);
            readLock.unlock();
        }, "READ_3").start();
    }

    private static void sleep(long millSeconds) {
        try {
            Thread.sleep(millSeconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

    * testLockWithDiffThread() 執行結果:

        1)在不同線程間,讀鎖間共享,不會進行鎖競爭,通過CPU調度依次執行

        2)寫鎖排斥,在嘗試獲取寫鎖時,會先判斷是否存在線程持有寫鎖或者讀寫,如果存在,則添加到AQS同步隊列中等待喚醒

        3)寫鎖等待後,再啓動一個讀鎖,此時因爲寫鎖等待,並且已經對低16位的獨佔鎖標識進行修改,且鎖線程與當前線程不一致。則當前讀鎖線程獲取鎖失敗,依次進入AQS隊列等待

    * testReadAndWriteLock 執行結果

        1)在同一線程後,嘗試獲取兩種鎖,從打印結果可以看出,線程獲取讀鎖後,再獲取寫鎖時阻塞,等待讀鎖釋放

        2)線程在獲取讀鎖後,對高16進行修改,並設置鎖線程爲當前線程

        3)線程繼續獲取寫鎖,因爲高位已經被修改,所以寫鎖獲取失敗,等待讀鎖釋放

    * testWriteAndReadLock 執行結果

        1)在同一線程中,嘗試獲取兩種所,從打印結果可以看出,線程獲取寫鎖後,再獲取讀鎖成功

        2)線程獲取寫鎖後,對低16位進行修改,並設置鎖線程爲當前線程

        3)線程繼續獲取讀鎖,雖然判斷獨佔線程已經存在,但是加鎖線程表示當前線程,所以線程獲取鎖成功

三,ReentrantReadWriteLock部分源碼分析

1,初始化部分

    * ReentrantReadWriteLock():調用重載構造器,並傳遞參數表示默認非公平鎖

public ReentrantReadWriteLock() {
	this(false);
}

    * ReentrantReadWriteLock(boolean fair)

public ReentrantReadWriteLock(boolean fair) {
	// 通過入參表示公平鎖還是非公平鎖
	sync = fair ? new FairSync() : new NonfairSync();
	// 初始化讀寫鎖對象
	readerLock = new ReadLock(this);
	writerLock = new WriteLock(this);
}

    * 初始化讀寫鎖

// 初始化讀鎖
protected ReadLock(ReentrantReadWriteLock lock) {
	sync = lock.sync;
}
// 初始化寫鎖
protected WriteLock(ReentrantReadWriteLock lock) {
	sync = lock.sync;
}

    * 獲取讀寫鎖

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

四,ReentrantReadWriteLock.ReadLock源碼分析

1,嘗試加鎖

    * tryLock():直接通過 Sync 嘗試加讀鎖

public boolean tryLock() {
	return sync.tryReadLock();
}

    * tryReadLock()

final boolean tryReadLock() {
	// 獲取當前線程
	Thread current = Thread.currentThread();
	// 自旋嘗試獲取鎖,可能存在線程競爭導致的CAS失敗問題
	for (;;) {
		// 獲取當前的加鎖次數,注意此處次數是經過高低位處理後的次數,並不是真實次數,需要進行解析
		int c = getState();
		// exclusiveCount:低16位解析,獲取獨佔鎖數量,判斷是否存在獨佔鎖
		// getExclusiveOwnerThread:判斷當前線程是否是鎖線程
		// 所以如果存在獨佔鎖,並且鎖線程不是當前線程,則嘗試失敗
		// 否則當前步驟成功
		if (exclusiveCount(c) != 0 &&
			getExclusiveOwnerThread() != current)
			return false;
		// 高16位解析,獲取共享鎖數量
		int r = sharedCount(c);
		// 共享鎖最大值判斷,
		// MAX_COUNT = (1 << SHARED_SHIFT) - 1;
		if (r == MAX_COUNT)
			throw new Error("Maximum lock count exceeded");
		// 按照重入邏輯,如果可以加鎖,則是對state+1
		// 但是共享鎖是對高16位進行操作,所以應該在高16位的基礎上加1,
		// SHARED_UNIT = (1 << SHARED_SHIFT);
		if (compareAndSetState(c, c + SHARED_UNIT)) {
			// r爲0,表示當前並沒有共享鎖進入,則初始化當前線程爲頭線程
			if (r == 0) {
				firstReader = current;
				firstReaderHoldCount = 1;
			// 當前線程重入,則對重入此時遞增
			} else if (firstReader == current) {
				firstReaderHoldCount++;
			} else {
				// 此處表示獲取共享鎖的線程不是當前鎖線程
				// 存在新線程嘗試獲取共享鎖,則cachedHoldCounter必定爲null
				HoldCounter rh = cachedHoldCounter;
				if (rh == null || rh.tid != getThreadId(current))
					// readHolds集成自ThreadLocal,爲每一個新線程分配一個HoldCounter
					cachedHoldCounter = rh = readHolds.get();
				// 可能存在其他途徑創建線程的HoldCounter,這樣在readHolds中可能不存在(個人理解)
				else if (rh.count == 0)
					readHolds.set(rh);
				// 初始化完成後,對count遞增,表示線程加鎖及重入
				rh.count++;
			}
			return true;
		}
	}
}

    * readHolds.get():此處涉及 ThreadLocal 的初始化部分

// ThreadLocalHoldCounter繼承自ThreadLocal
// 泛型表示ThreadLocal爲每一個線程分配一個 HoldCounter 對象
// 當前類重寫了父類的initialValue()方法,並初始化了一個HoldCounter對象
// 表示 ThreadLocalHoldCounter 默認爲每一個線程分配一個已經初始化好的對象
// 每一次get時,如果獲取不到線程已經存儲的信息,則直接返回一個新對象
static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
	public HoldCounter initialValue() {
		return new HoldCounter();
	}
}

2,加鎖

    * lock()

public void lock() {
	sync.acquireShared(1);
}

public final void acquireShared(int arg) {
	if (tryAcquireShared(arg) < 0)
		doAcquireShared(arg);
}

    * tryAcquireShared(int unused)

protected final int tryAcquireShared(int unused) {
	Thread current = Thread.currentThread();
	int c = getState();
	// 存在寫鎖,並且不是當前線程獲取,則獲取鎖失敗
	// 此處不排除存在寫鎖,如果存在寫鎖則寫鎖爲當前線程持有
	if (exclusiveCount(c) != 0 &&
		getExclusiveOwnerThread() != current)
		return -1;
	// readerShouldBlock():判斷是否存在下一個節點,且下一個節點不是共享節點
	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);
}

    * fullTryAcquireShared(Thread current)

final int fullTryAcquireShared(Thread current) {
	HoldCounter rh = null;
	for (;;) {
		int c = getState();
		// 判斷是否獨佔鎖,且不是當前線程
		// 當前線程獲取獨佔鎖後,可繼續獲取共享鎖
		if (exclusiveCount(c) != 0) {
			if (getExclusiveOwnerThread() != current)
				return -1;
		// 存在下一個節點,並且下一個不是共享鎖節點,則需要阻塞
		} else if (readerShouldBlock()) {
			// firstReader表示當前線程,說明正在執行中,默認不阻塞
			if (firstReader == current) {
			} else {
				// 此處判斷當前線程是否在執行中,rh.count表示重入
				// 如果在執行中,則繼續可以獲取執行,如果不在執行中,則獲取失敗
				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;
		}
	}
}

    * readerShouldBlock():存在下一個節點,並且下一個節點不是共享節點,返回true,否則返回false

final boolean readerShouldBlock() {
	return apparentlyFirstQueuedIsExclusive();
}

// 此處判斷是否存在下一個節點,以及下一個節點是否爲共享節點(取反)
final boolean apparentlyFirstQueuedIsExclusive() {
	Node h, s;
	return (h = head) != null &&
		(s = h.next)  != null &&
		!s.isShared()         &&
		s.thread != null;
}

3,釋放鎖

    * unlock()

public void unlock() {
	sync.releaseShared(1);
}

public final boolean releaseShared(int arg) {
	if (tryReleaseShared(arg)) {
		doReleaseShared();
		return true;
	}
	return false;
}

    * tryReleaseShared(int unused)

protected final boolean tryReleaseShared(int unused) {
	Thread current = Thread.currentThread();
	// 判斷當前線程是否firstReader
	// 此處條件判斷,主要爲了遞減線程重入次數,如果可以釋放,則對關鍵標識對象置空,幫助GC,並方便後續操作判斷
	if (firstReader == current) {
		// 繼續判斷firstReaderHoldCount重入次數,如果爲1,說明可以徹底釋放,重置firstReader
		// 不爲1,遞減即可
		if (firstReaderHoldCount == 1)
			firstReader = null;
		else
			firstReaderHoldCount--;
	} else {
		// 當前線程不是firstReader,則從readHolds中獲取,並判斷count重入次數
		HoldCounter rh = cachedHoldCounter;
		if (rh == null || rh.tid != getThreadId(current))
			rh = readHolds.get();
		int count = rh.count;
		// count <=1,同樣表示徹底釋放,從readHolds中移除
		if (count <= 1) {
			readHolds.remove();
			if (count <= 0)
				throw unmatchedUnlockException();
		}
		--rh.count;
	}
	for (;;) {
		// 獲取共享鎖的重入次數,並遞減,是否爲0標識
		int c = getState();
		int nextc = c - SHARED_UNIT;
		if (compareAndSetState(c, nextc))
			return nextc == 0;
	}
}

五,ReentrantReadWriteLock.WriteLock源碼分析

1,嘗試加鎖

    * tryLock( )

public boolean tryLock( ) {
	return sync.tryWriteLock();
}

    * tryWriteLock()

final boolean tryWriteLock() {
	Thread current = Thread.currentThread();
	int c = getState();
	// c不爲0,表示存在獨佔鎖或者共享鎖
	if (c != 0) {
		// 獲取獨佔鎖重入次數
		int w = exclusiveCount(c);
		// w爲0,說明獨佔鎖爲空,則表示存在共享鎖,獲取鎖失敗
		// w不爲0,並且鎖線程不是當前線程,說明存在其他線程持有獨佔鎖,獲取鎖失敗
		// 此處證明在同一線程下,獲取共享鎖後,不可獲取獨佔鎖
		if (w == 0 || current != getExclusiveOwnerThread())
			return false;
		if (w == MAX_COUNT)
			throw new Error("Maximum lock count exceeded");
	}
	// CAS設置重入狀態,設置成功後,添加鎖線程爲當前線程
	if (!compareAndSetState(c, c + 1))
		return false;
	setExclusiveOwnerThread(current);
	return true;
}

2,加鎖

    * lock()

public void lock() {
	sync.acquire(1);
}

public final void acquire(int arg) {
	if (!tryAcquire(arg) &&
		acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
		selfInterrupt();
}

    * tryAcquire(int acquires):此處嘗試加鎖與上一步嘗試加鎖基本一致,只是加了一步判斷

protected final boolean tryAcquire(int acquires) {
	Thread current = Thread.currentThread();
	int c = getState();
	int w = exclusiveCount(c);
	if (c != 0) {
		if (w == 0 || current != getExclusiveOwnerThread())
			return false;
		if (w + exclusiveCount(acquires) > MAX_COUNT)
			throw new Error("Maximum lock count exceeded");
		setState(c + acquires);
		return true;
	}
	// writerShouldBlock:判斷寫鎖是否需要阻塞
	if (writerShouldBlock() ||
		!compareAndSetState(c, c + acquires))
		return false;
	setExclusiveOwnerThread(current);
	return true;
}

    * writerShouldBlock():該方法在非公平鎖中默認返回false,再公平鎖實現中,進行了AQS隊列存在性校驗,保證順序執行

// 非公平鎖
final boolean writerShouldBlock() {
	return false; 
}

// 公平鎖
final boolean writerShouldBlock() {
	return hasQueuedPredecessors();
}
public final boolean hasQueuedPredecessors() {
	Node t = tail;
	Node h = head;
	Node s;
	return h != t &&
		((s = h.next) == null || s.thread != Thread.currentThread());
}

3,釋放鎖

    * unlock()

public void unlock() {
	sync.release(1);
}

public final boolean release(int arg) {
	if (tryRelease(arg)) {
		Node h = head;
		if (h != null && h.waitStatus != 0)
			unparkSuccessor(h);
		return true;
	}
	return false;
}

    * tryRelease(int releases)

protected final boolean tryRelease(int releases) {
	// 判斷當前線程是否鎖線程
	if (!isHeldExclusively())
		throw new IllegalMonitorStateException();
	// 獲取釋放後的獨佔鎖重入次數
	int nextc = getState() - releases;
	boolean free = exclusiveCount(nextc) == 0;
	// 重入次數爲0,則釋放成功,置空鎖線程,
	if (free)
		setExclusiveOwnerThread(null);
	setState(nextc);
	return free;
}

 

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