AQS之獨(dú)占鎖
AQS之共享鎖
AQS之Condition
在了解了AQS的實(shí)現(xiàn)原理之后再來看這些同步器會(huì)覺得很親切,這其實(shí)也是在告訴自己,基礎(chǔ)的重要性
ReentrantLock
Lock lock = new ReentrantLock();
for (int i = 0; i < 3; i++) {
new Thread(() -> {
lock.lock();
System.out.println(Thread.currentThread().getName() + " " + LocalDateTime.now());
sleep(TimeUnit.SECONDS, 2);
lock.unlock();
}).start();
}
---------------------------------執(zhí)行結(jié)果------------------------------------
Thread-0 2020-01-01T17:12:24.678
Thread-1 2020-01-01T17:12:26.681
Thread-2 2020-01-01T17:12:28.681
- 實(shí)現(xiàn)原理基于
獨(dú)占鎖
-
公平鎖
在tryAcquire
方法中會(huì)先判斷隊(duì)列中有沒有阻塞節(jié)點(diǎn),有就加入隊(duì)列,沒有就通過CAS嘗試獲取鎖 -
非公平鎖
在tryAcquire
中不管隊(duì)列中有沒有阻塞節(jié)點(diǎn),直接先通過CAS嘗試獲取鎖,獲取成功就返回,獲取失敗就加入阻塞隊(duì)列
CountDownLatch
CountDownLatch countDownLatch = new CountDownLatch(3);
new Thread(() -> {
sleep(TimeUnit.MILLISECONDS, 80);
System.out.println(Thread.currentThread().getName() + " Finished");
countDownLatch.countDown();
}).start();
new Thread(() -> {
sleep(TimeUnit.MILLISECONDS, 50);
System.out.println(Thread.currentThread().getName() + " Finished");
countDownLatch.countDown();
}).start();
new Thread(() -> {
sleep(TimeUnit.MILLISECONDS, 60);
System.out.println(Thread.currentThread().getName() + " Finished");
countDownLatch.countDown();
}).start();
new Thread(() -> {
sleep(TimeUnit.MILLISECONDS, 60);
System.out.println(Thread.currentThread().getName() + " Finished");
countDownLatch.countDown();
}).start();
countDownLatch.await();
System.out.println("All Finished");
---------------------------------執(zhí)行結(jié)果------------------------------------
Thread-1 Finished
Thread-2 Finished
Thread-3 Finished
All Finished
Thread-0 Finished
- 實(shí)現(xiàn)原理基于
共享鎖
- 在初始化的時(shí)候傳入一個(gè)變量,該變量即代表同步器中
state
的值 - 調(diào)用
CountDownLatch#await
方法的時(shí)候,會(huì)判斷state
的值是否等于0,不等于0就添加到阻塞隊(duì)列,等于0就直接返回 - 調(diào)用
CountDownLatch#countDown
方法的時(shí)候,state
減1,判斷state
的值是否等于0,等于0就釋放因調(diào)用CountDownLatch#await
方法而阻塞的線程,不等于0就直接返回
CyclicBarrier
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("阻塞解除之后執(zhí)行一些邏輯 " + LocalDateTime.now()));
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " doXX");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " doXX");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
sleep(TimeUnit.SECONDS, 2);
}
---------------------------------執(zhí)行結(jié)果------------------------------------
Thread-0 doXX
Thread-1 doXX
阻塞解除之后執(zhí)行一些邏輯 2020-01-01T14:19:15.735
Thread-2 doXX
Thread-3 doXX
阻塞解除之后執(zhí)行一些邏輯 2020-01-01T14:19:17.706
Thread-4 doXX
Thread-5 doXX
阻塞解除之后執(zhí)行一些邏輯 2020-01-01T14:19:19.706
字面意思就是循環(huán)壁壘
,使用上與CountDownLatch
類似,不過實(shí)現(xiàn)上完全不一樣,CyclicBarrier
統(tǒng)計(jì)的的是調(diào)用了CyclicBarrier#await
方法的線程數(shù),當(dāng)線程數(shù)達(dá)到了CyclicBarrier
初始時(shí)規(guī)定的數(shù)目時(shí),所有進(jìn)入等待狀態(tài)的線程將被喚醒然后進(jìn)入下一輪,可以重復(fù)使用
- 實(shí)現(xiàn)原理是基于
ReentrantLock
和Condition
- 執(zhí)行
CyclicBarrier#await
之前,需要先執(zhí)行ReentrantLock#lock
方法,完成之后執(zhí)行ReentrantLock#unlock
方法,即通過ReentrantLock
保證執(zhí)行CyclicBarrier#await
方法是安全的 - 在執(zhí)行
CyclicBarrier#await
方法的時(shí)候,不滿足釋放條件(調(diào)用CyclicBarrier#await
方法的線程數(shù)不等于初始值)時(shí),會(huì)調(diào)用Condition#await
方法是當(dāng)前線程阻塞,滿足釋放條件時(shí)會(huì)調(diào)用Condition#signalAll
喚醒所有阻塞的線程然后進(jìn)入下一輪 -
CyclicBarrier
中有一個(gè)內(nèi)部類Generation
,該內(nèi)部類就表示一輪一輪循環(huán)的意思,當(dāng)滿足釋放條件時(shí),除了喚醒所有因調(diào)用CyclicBarrier#await
方法而阻塞的線程,還會(huì)生成一個(gè)新的Generation
對(duì)象,代表下一輪開始
Semaphore
信號(hào)量
,可以用來控制同時(shí)訪問資源的線程個(gè)數(shù),比如可以用在對(duì)線程數(shù)的限流,在初始化的時(shí)候需要用戶傳入許可的數(shù)量,通過Semaphore#acquire
方法獲取一個(gè)許可,如果Semaphore
還有許可可獲取就直接返回,否則阻塞當(dāng)前線程
Semaphore semaphore = new Semaphore(2);
for (int i = 0; i < 4; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "訪問資源");
sleep(TimeUnit.MILLISECONDS, 10 + new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "釋放資源");
semaphore.release();
}
}).start();
}
---------------------------------執(zhí)行結(jié)果------------------------------------
Thread-1訪問資源
Thread-0訪問資源
Thread-0釋放資源
Thread-2訪問資源
Thread-1釋放資源
Thread-3訪問資源
Thread-2釋放資源
Thread-3釋放資源
- 實(shí)現(xiàn)原理基于
共享鎖
- 內(nèi)部類
Sync
實(shí)現(xiàn)了AbstractQueuedSynchronizer
,Sync
實(shí)現(xiàn)類有兩個(gè),對(duì)應(yīng)公平鎖和非公平鎖 - 簡(jiǎn)單來講,
Semaphore
其實(shí)就是一個(gè)共享鎖
,根據(jù)我們對(duì)共享鎖
的了解,共享鎖
表示同一時(shí)刻最多有多少個(gè)線程持有鎖,這和Semaphore
的特性是一致的,所以Semaphore
只需要再封裝一層API,調(diào)用Semaphore#acquire
方法時(shí)候獲取鎖或阻塞,調(diào)用,調(diào)用
Semaphore#release`通過自旋釋放鎖就可以了
DelayQueue
- 實(shí)現(xiàn)原理基于
ReentrantLock
和Condition
-
優(yōu)先級(jí)
無界
阻塞隊(duì)列 - 元素必須實(shí)現(xiàn)
Delayed
接口,Delayed#getDelay
方法返回值<=0
代表該元素延遲時(shí)間已到,可以出隊(duì)了 - 基于
優(yōu)先級(jí)
保證元素插入的順序,基于Delayed#getDelay
來控制元素延遲的時(shí)間,基于Condition
控制在獲取元素時(shí)是阻塞還是返回(隊(duì)首元素)
LinkedBlockingQueue
- 實(shí)現(xiàn)原理基于2個(gè)
ReentrantLock
和2個(gè)Condition
,分別為ReentrantLock存取鎖
和Condition存取鎖
-
有界
阻塞隊(duì)列,如果不指定,容量默認(rèn)為Integer.MAX_VALUE
- 鏈表結(jié)構(gòu),每個(gè)元素會(huì)被封裝成一個(gè)
Node
節(jié)點(diǎn),每個(gè)Node
節(jié)點(diǎn)有一個(gè)next指針 -
尾進(jìn)頭出
,添加元素的時(shí)候放到尾部,獲取元素的時(shí)候放到頭部
添加元素
涉及到的方法:LinkedBlockingQueue#put
,LinkedBlockingQueue#offer
,如果隊(duì)列滿了,前者會(huì)阻塞,后者不會(huì)阻塞
- 先獲取
ReentrantLock存鎖
- 如果已經(jīng)達(dá)到容量上限,就通過
Condition存鎖
阻塞當(dāng)前線程,否則添加元素 -
入隊(duì)
,將當(dāng)前元素添加到隊(duì)尾,將上次隊(duì)位元素的next指針指向該元素,更新last
指向 - 容量加1,如果
容量==0
,喚醒Condition寫鎖
獲取元素
涉及到的方法:LinkedBlockingQueue#take
,LinkedBlockingQueue#poll
,如果隊(duì)列空了,前者會(huì)阻塞,后者不會(huì)阻塞
- 先獲取
ReentrantLock寫鎖
- 如果隊(duì)列里面沒有元素,就通過
Condition寫鎖
阻塞當(dāng)前線程,否則獲取元素 -
出隊(duì)
,從隊(duì)首去取出一個(gè)元素,更新head
指向 - 容量減1,如果
容量滿了
,喚醒Condition讀鎖
ArrayBlockingQueue
- 實(shí)現(xiàn)原理基于1個(gè)
ReentrantLock
和2個(gè)Condition
,兩個(gè)Condition
分別用于判斷是否為空和是否已滿 -
有界
阻塞隊(duì)列,基于final數(shù)組
,自然是有界的 - 數(shù)組結(jié)構(gòu),基于
final數(shù)組
,,在初始化ArrayBlockingQueue
的時(shí)候需要指定容量
添加元素
涉及到的方法:ArrayBlockingQueue#put
,ArrayBlockingQueue#offer
,如果隊(duì)列滿了,前者會(huì)阻塞,后者不會(huì)阻塞
- 獲取
ReentrantLock
鎖 - 如果隊(duì)列滿了,通過判斷是否已滿的
Condition
阻塞當(dāng)前線程 - 有一個(gè)變量
putIndex
用于記錄下次添加元素時(shí)對(duì)應(yīng)的數(shù)組下標(biāo),當(dāng)takeIndex==隊(duì)列.length
的時(shí)候,重置該變量為0 - 喚醒判斷是否為空的
Condition
獲取元素
涉及到的方法:ArrayBlockingQueue#take
,ArrayBlockingQueue#poll
,如果隊(duì)列空了,前者會(huì)阻塞,后者不會(huì)阻塞
- 獲取
ReentrantLock
鎖 - 如果隊(duì)列為空了,通過判斷是否為空的
Condition
阻塞當(dāng)前線程 - 有一個(gè)變量
takeIndex
用于記錄下次獲取元素時(shí)對(duì)應(yīng)的數(shù)組下標(biāo),當(dāng)takeIndex==隊(duì)列.length
的時(shí)候,重置該變量為0 - 喚醒判斷是否已滿的
Condition
LinkedTransferQueue
進(jìn)行線程間數(shù)據(jù)交換的利器 todo
SynchronousQueue
PriorityBlockingQueue
- 實(shí)現(xiàn)原理基于
ReentrantLock
和Condition
-
優(yōu)先級(jí)
無界
阻塞隊(duì)列,優(yōu)先級(jí)
的實(shí)現(xiàn)基于二叉堆
- 值不允許
null
,且需要實(shí)現(xiàn)Comparable
接口
優(yōu)先級(jí)的 無界阻塞隊(duì)列
,優(yōu)先級(jí)
可以基于自然排序,也可以基于Comparable
接口,取決于你使用哪個(gè)構(gòu)造函數(shù)
添加元素
涉及到的方法: PriorityBlockingQueue#add
PriorityBlockingQueue#offer
- 先通過
ReentrantLock
獲取鎖 - 判斷
size >= queue.length
,如果條件成立就擴(kuò)容
3.通過Comparable#
和二叉堆
便利找到合適的位置插入元素 -
size
加1 - 喚醒因執(zhí)行了
PriorityBlockingQueue#take
方法而阻塞的線程(即隊(duì)列中沒有元素的時(shí)候),這個(gè)通過Condition
實(shí)現(xiàn) - 釋放鎖
獲取元素
涉及到的方法: PriorityBlockingQueue#poll
PriorityBlockingQueue#take
- 在調(diào)用這些方法之前都需要先通過
ReentrantLock
獲取鎖 -
PriorityBlockingQueue#poll
方法,在隊(duì)列中沒有元素的時(shí)候直接返回null
,不會(huì)阻塞當(dāng)前線程 -
PriorityBlockingQueue#take
方法,在隊(duì)列中沒有元素的時(shí)候會(huì)阻塞當(dāng)前線程,知道隊(duì)列中有元素然后再被喚醒返回,基于Condition
實(shí)現(xiàn)
隊(duì)列擴(kuò)容
涉及到的方法: PriorityBlockingQueue#tryGrow
- 執(zhí)行
ReentrantLock#unlock
方法,釋放ReentrantLock
鎖,為什么要釋放這個(gè)鎖呢?我猜這里是為了提高性能,在擴(kuò)容之前先釋放鎖,然后通過一個(gè)CAS變量來控制擴(kuò)容的并發(fā)問題,這樣在擴(kuò)容期間就不會(huì)接阻塞其他調(diào)用線程,比如take
操作,很妙 - 當(dāng)前是否正在擴(kuò)容通過一個(gè)
volatile
變量表示,0表示目前不在擴(kuò)容,1表示正在擴(kuò)容,每次擴(kuò)容之前通過CAS將其設(shè)置為1,如果CAS失敗說明目前有其他線程正在擴(kuò)容,此時(shí)不做處理 - 擴(kuò)容的時(shí)候先判斷當(dāng)前容量是否小于64,如果小于64就對(duì)容量
*2+2
;如果不小于64,則對(duì)容量*1.5
- 重新基于該容量創(chuàng)建一個(gè)新的
Object[]
- 如果有并發(fā)問題,就通過
Thread#yield
讓出當(dāng)前CPU - 通過
System#arraycopy
對(duì)行隊(duì)列賦值,在賦值之前需要先通過ReentrantLock#lock
再次獲取鎖
CopyOnWriteArrayList
可以將它看成是一個(gè)線程安全的ArrayList
,在涉及到修改操作時(shí),通過ReentrantLock
獲取鎖,然后復(fù)制一個(gè)新的數(shù)組去修改,基于volatile
語義可以讀數(shù)據(jù)時(shí)不會(huì)有問題,適用于讀多寫少的場(chǎng)景,如果寫比較多的比較影響性能
- 實(shí)現(xiàn)原理基于
ReentrantLock
和volatile
- 元素可以為
null
獲取元素
例如CopyOnWriteArrayList#get
方法,直接返回?cái)?shù)組下標(biāo)對(duì)應(yīng)的元素即可
修改元素
例如CopyOnWriteArrayList#set
CopyOnWriteArrayList#add`方法
- 先獲取
ReentrantLock
鎖 - 基于原數(shù)組創(chuàng)建一個(gè)新的數(shù)組,然后使引用指向新數(shù)組
- 釋放鎖
CopyOnWriteArraySet
內(nèi)部持有一個(gè)CopyOnWriteArrayList
引用,也就是它的實(shí)現(xiàn)完全是基于CopyOnWriteArrayList
,那它是如何保證元素不唯一呢?在CopyOnWriteArrayList
中有一個(gè)addIfAbsent
方法,該方法會(huì)通過遍歷的方式去判斷你要添加的元素是否存在.
適合讀多寫少的場(chǎng)景
ReentrantReadWriteLock
- 持有寫鎖的時(shí)候不能申請(qǐng)讀鎖,持有讀鎖的時(shí)候不能申請(qǐng)寫鎖,但鎖降級(jí)的時(shí)候是個(gè)例外(持有寫鎖的情況下降級(jí)成讀鎖,實(shí)際上是持有寫鎖的時(shí)候再去申請(qǐng)讀鎖,因?yàn)槎际潜煌粋€(gè)線程占有,所以不會(huì)有問題)
- 寫鎖,獨(dú)占鎖,int類型低16位表示,當(dāng)一個(gè)線程持有寫鎖的時(shí)候,其它線程不能獲取讀鎖,只能在阻塞隊(duì)列排隊(duì),寫鎖可以降級(jí)成讀鎖
- 讀鎖,共享鎖,int類型高16位表示,當(dāng)一個(gè)線程持有讀鎖的時(shí)候,其他線程還可以申請(qǐng)讀鎖,但不能申請(qǐng)寫鎖,讀鎖不可以降級(jí)成寫鎖
使用示例
StringBuilder data = new StringBuilder("data");
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
new Thread((() -> {
// sleep一會(huì),讓寫鎖先持有鎖
sleep(TimeUnit.MILLISECONDS, 10);
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "獲得讀鎖 " + LocalDateTime.now());
System.out.println(Thread.currentThread().getName() + data);
readWriteLock.readLock().unlock();
}), "readLock ").start();
new Thread((() -> {
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "獲得寫鎖 " + LocalDateTime.now());
sleep(TimeUnit.SECONDS, 3);
data.append("666");
// 鎖降級(jí) 這里這樣子使用降級(jí)感覺沒有什么意思,那鎖降級(jí)一般用到什么場(chǎng)景
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + data);
readWriteLock.writeLock().unlock();
}), "writeLock ").start();
構(gòu)造函數(shù)
public ReentrantReadWriteLock() {
this(false);
}
// 可以在創(chuàng)建ReentrantReadWriteLock時(shí)選擇公平模式還是非公平模式
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
- 可以在創(chuàng)建
ReentrantReadWriteLock
時(shí)選擇使用公平鎖還是非公平鎖 - 內(nèi)部類
Sync
繼承自AbstractQueuedSynchronizer
,它負(fù)責(zé)實(shí)現(xiàn)同步器的模板方法,是實(shí)現(xiàn)同步器的關(guān)鍵 -
ReadLock
和WriteLock
實(shí)現(xiàn)了Lock
接口,可以將它們看作是API層,具體邏輯委托給Sync
實(shí)現(xiàn),面向用戶
Sync
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;
/** Returns the number of shared holds represented in count */
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
/** Returns the number of exclusive holds represented in count */
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
獲取讀鎖
public void lock() {
sync.acquireShared(1);
}
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// 其實(shí)這里就涉及到鎖降級(jí),如果當(dāng)前已經(jīng)有寫鎖,返回-1,將它加入到阻塞隊(duì)列, 否則繼續(xù)嘗試獲取讀鎖
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
// readerShouldBlock主要是針對(duì)公平鎖和非公平鎖, `c + SHARED_UNIT`是因?yàn)楣蚕礞i用的是高16位
if (!readerShouldBlock() && r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)) {
if (r == 0) {
// firstReader是把讀鎖狀態(tài)從0變成1的那個(gè)線程
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
// 鎖重入
firstReaderHoldCount++;
} else {
// cachedHoldCounter是上一個(gè)獲取鎖成功的線程
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;
}
// 上面的if失敗了,即通過自旋獲取鎖
return fullTryAcquireShared(current);
}
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;
}
}
}
釋放讀鎖
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
// 如果 firstReader 是當(dāng)前線程
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
// 并且firstReaderHoldCount == 1,說明釋放鎖之后需要重置firstReader
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))
// Releasing the read lock has no effect on readers,
// but it may allow waiting writers to proceed if
// both read and write locks are now free.
return nextc == 0;
}
}
- 讀鎖和寫鎖不能同時(shí)使用,所以釋放讀鎖的時(shí)候按理來說并不需要去喚醒節(jié)點(diǎn)
- 但如果
state==0
,需要喚醒阻塞的寫鎖
獲取寫鎖
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
// state != 0 && w==0 說明有讀鎖
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;
}
// writerShouldBlock用于確定公平和非公平模式
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
判斷是又讀鎖,判斷是否鎖重入,通過CAS設(shè)置狀態(tài)
釋放寫鎖
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;
}
和正常的獨(dú)占鎖釋放一樣