---
title: ä»ReentrantLockçå®ç°çAQSçåçååºç¨
description: ReentrantLockä¸AQSåçæ·±åº¦è§£æï¼è¯¦è§£ReentrantLockå¯éå
¥éå®ç°ãå
¬å¹³éä¸éå
¬å¹³éåºå«ãåºäºAQSçå éè§£éæµç¨ãä¸synchronizedæ§è½å¯¹æ¯ã
category: Java
tag:
- Javaå¹¶å
head:
- - meta
- name: keywords
content: ReentrantLock,AQS,å
¬å¹³é,éå
¬å¹³é,å¯éå
¥é,lock unlock,ReentrantLockåç,synchronized对æ¯
---
> æ¬æè½¬è½½èªï¼
>
> ä½è
ï¼ç¾å¢ææ¯å¢é
Java ä¸ç大é¨ååæ¥ç±»ï¼SemaphoreãReentrantLock çï¼é½æ¯åºäº AbstractQueuedSynchronizerï¼ç®ç§°ä¸º AQSï¼å®ç°çãAQS æ¯ä¸ç§æä¾äºååå¼ç®¡çåæ¥ç¶æãé»å¡åå¤é线ç¨åè½ä»¥åé忍¡åçç®åæ¡æ¶ã
æ¬æä¼ä»åºç¨å±éæ¸æ·±å
¥å°åçå±ï¼å¹¶éè¿ ReentrantLock çåºæ¬ç¹æ§å ReentrantLock ä¸ AQS çå
³èï¼æ¥æ·±å
¥è§£è¯» AQS ç¸å
³ç¬å éçç¥è¯ç¹ï¼åæ¶éåé®ççæ¨¡å¼æ¥å¸®å©å¤§å®¶çè§£ AQSãç±äºç¯å¹
åå ï¼æ¬ç¯æç« 主è¦éè¿° AQS ä¸ç¬å éçé»è¾å Sync Queueï¼ä¸è®²è¿°å
å«å
±äº«éå Condition Queue çé¨åï¼æ¬ç¯æç« æ ¸å¿ä¸º AQS åçåæï¼åªæ¯ç®åä»ç»äº ReentrantLockï¼æå
´è¶£åå¦å¯ä»¥é
读ä¸ä¸ ReentrantLock çæºç ï¼ã
## 1 ReentrantLock
### 1.1 ReentrantLock ç¹æ§æ¦è§
ReentrantLock ææä¸ºå¯éå
¥éï¼æçæ¯ä¸ä¸ªçº¿ç¨è½å¤å¯¹ä¸ä¸ªä¸´çèµæºéå¤å éã为äºå¸®å©å¤§å®¶æ´å¥½å°çè§£ ReentrantLock çç¹æ§ï¼æä»¬å
å° ReentrantLock è·å¸¸ç¨ç Synchronized è¿è¡æ¯è¾ï¼å
¶ç¹æ§å¦ä¸ï¼èè²é¨å为æ¬ç¯æç« 主è¦åæçç¹ï¼ï¼

ä¸é¢éè¿ä¼ªä»£ç ï¼è¿è¡æ´å ç´è§çæ¯è¾ï¼
```java
// **************************Synchronizedçä½¿ç¨æ¹å¼**************************
// 1.ç¨äºä»£ç å
synchronized (this) {}
// 2.ç¨äºå¯¹è±¡
synchronized (object) {}
// 3.ç¨äºæ¹æ³
public synchronized void test () {}
// 4.å¯éå
¥
for (int i = 0; i < 100; i++) {
synchronized (this) {}
}
// **************************ReentrantLockçä½¿ç¨æ¹å¼**************************
public void test () throw Exception {
// 1.åå§åéæ©å
¬å¹³éãéå
¬å¹³é
ReentrantLock lock = new ReentrantLock(true);
// 2.å¯ç¨äºä»£ç å
lock.lock();
try {
try {
// 3.æ¯æå¤ç§å éæ¹å¼ï¼æ¯è¾çµæ´»; å
·æå¯éå
¥ç¹æ§
if(lock.tryLock(100, TimeUnit.MILLISECONDS)){ }
} finally {
// 4.æå¨éæ¾é
lock.unlock()
}
} finally {
lock.unlock();
}
}
```
### 1.2 ReentrantLock ä¸ AQS çå
³è
éè¿ä¸ææä»¬å·²ç»äºè§£ï¼ReentrantLock æ¯æå
¬å¹³éåéå
¬å¹³éï¼å
³äºå
¬å¹³éåéå
¬å¹³éçåçåæï¼å¯åèã[ä¸å¯ä¸è¯´ç Javaâéâäº](https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651749434&idx=3&sn=5ffa63ad47fe166f2f1a9f604ed10091&chksm=bd12a5778a652c61509d9e718ab086ff27ad8768586ea9b38c3dcf9e017a8e49bcae3df9bcc8&scene=38#wechat_redirect)ãï¼ï¼å¹¶ä¸ ReentrantLock çåºå±å°±æ¯ç± AQS æ¥å®ç°çãé£ä¹ ReentrantLock æ¯å¦ä½éè¿å
¬å¹³éåéå
¬å¹³éä¸ AQS å
³èèµ·æ¥å¢ï¼ æä»¬çéä»è¿ä¸¤è
çå éè¿ç¨æ¥çè§£ä¸ä¸å®ä»¬ä¸ AQS ä¹é´çå
³ç³»ï¼å éè¿ç¨ä¸ä¸ AQS çå
³èæ¯è¾ææ¾ï¼è§£éæµç¨åç»ä¼ä»ç»ï¼ã
éå
¬å¹³éæºç ä¸çå éæµç¨å¦ä¸ï¼
```java
// java.util.concurrent.locks.ReentrantLock#NonfairSync
// éå
¬å¹³é
static final class NonfairSync extends Sync {
...
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
...
}
```
è¿å代ç çå«ä¹ä¸ºï¼
- è¥éè¿ CAS 设置åé Stateï¼åæ¥ç¶æï¼æåï¼ä¹å°±æ¯è·åéæåï¼åå°å½å线ç¨è®¾ç½®ä¸ºç¬å 线ç¨ã
- è¥éè¿ CAS 设置åé Stateï¼åæ¥ç¶æï¼å¤±è´¥ï¼ä¹å°±æ¯è·åé失败ï¼åè¿å
¥ Acquire æ¹æ³è¿è¡åç»å¤çã
ç¬¬ä¸æ¥å¾å¥½çè§£ï¼ä½ç¬¬äºæ¥è·åé失败åï¼åç»çå¤ççç¥æ¯æä¹æ ·çå¢ï¼è¿åå¯è½ä¼æä»¥ä¸æèï¼
- æä¸ªçº¿ç¨è·åé失败çåç»æµç¨æ¯ä»ä¹å¢ï¼æä»¥ä¸ä¸¤ç§å¯è½ï¼
(1) å°å½å线ç¨è·éç»æè®¾ç½®ä¸ºå¤±è´¥ï¼è·åéæµç¨ç»æãè¿ç§è®¾è®¡ä¼æå¤§éä½ç³»ç»çå¹¶å度ï¼å¹¶ä¸æ»¡è¶³æä»¬å®é
çéæ±ãæä»¥å°±éè¦ä¸é¢è¿ç§æµç¨ï¼ä¹å°±æ¯ AQS æ¡æ¶çå¤çæµç¨ã
(2) åå¨æç§æéçåæºå¶ï¼çº¿ç¨ç»§ç»çå¾
ï¼ä»ç¶ä¿çè·åéçå¯è½ï¼è·åéæµç¨ä»å¨ç»§ç»ã
- 对äºé®é¢ 1 ç第äºç§æ
åµï¼æ¢ç¶è¯´å°äºæéçåæºå¶ï¼é£ä¹å°±ä¸å®ä¼ææç§éåå½¢æï¼è¿æ ·çé忝ä»ä¹æ°æ®ç»æå¢ï¼
- å¤äºæéçåæºå¶ä¸ç线ç¨ï¼ä»ä¹æ¶åå¯ä»¥ææºä¼è·åéå¢ï¼
- 妿å¤äºæéçåæºå¶ä¸ç线ç¨ä¸ç´æ æ³è·åéï¼è¿æ¯éè¦ä¸ç´çå¾
åï¼è¿æ¯æå«ççç¥æ¥è§£å³è¿ä¸é®é¢ï¼
带çéå
¬å¹³éçè¿äºé®é¢ï¼åçä¸å
¬å¹³éæºç ä¸è·éçæ¹å¼ï¼
```java
// java.util.concurrent.locks.ReentrantLock#FairSync
static final class FairSync extends Sync {
...
final void lock() {
acquire(1);
}
...
}
```
çå°è¿å代ç ï¼æä»¬å¯è½ä¼åå¨è¿ç§çé®ï¼Lock 彿°éè¿ Acquire æ¹æ³è¿è¡å éï¼ä½æ¯å
·ä½æ¯å¦ä½å éçå¢ï¼
ç»åå
¬å¹³éåéå
¬å¹³éçå éæµç¨ï¼è½ç¶æµç¨ä¸æä¸å®çä¸åï¼ä½æ¯é½è°ç¨äº Acquire æ¹æ³ï¼è Acquire æ¹æ³æ¯ FairSync å UnfairSync çç¶ç±» AQS ä¸çæ ¸å¿æ¹æ³ã
对äºä¸è¾¹æå°çé®é¢ï¼å
¶å®å¨ ReentrantLock ç±»æºç ä¸é½æ æ³è§£çï¼èè¿äºé®é¢ççæ¡ï¼é½æ¯ä½äº Acquire æ¹æ³æå¨çç±» AbstractQueuedSynchronizer ä¸ï¼ä¹å°±æ¯æ¬æçæ ¸å¿ââAQSãä¸é¢æä»¬ä¼å¯¹ AQS 以å ReentrantLock å AQS çå
³èå详ç»ä»ç»ï¼ç¸å
³é®é¢çæ¡ä¼å¨ 2.3.5 å°èä¸è§£çï¼ã
## 2 AQS
é¦å
ï¼æä»¬éè¿ä¸é¢çæ¶æå¾æ¥æ´ä½äºè§£ä¸ä¸ AQS æ¡æ¶ï¼

- ä¸å¾ä¸æé¢è²ç为 Methodï¼æ é¢è²ç为 Attributionã
- æ»çæ¥è¯´ï¼AQS æ¡æ¶å
±å为äºå±ï¼èªä¸èä¸ç±æµ
å
¥æ·±ï¼ä» AQS 坹夿´é²ç API å°åºå±åºç¡æ°æ®ã
- 彿èªå®ä¹åæ¥å¨æ¥å
¥æ¶ï¼åªééå第ä¸å±æéè¦çé¨åæ¹æ³å³å¯ï¼ä¸éè¦å
³æ³¨åºå±å
·ä½çå®ç°æµç¨ãå½èªå®ä¹åæ¥å¨è¿è¡å éæè
è§£éæä½æ¶ï¼å
ç»è¿ç¬¬ä¸å±ç API è¿å
¥ AQS å
鍿¹æ³ï¼ç¶åç»è¿ç¬¬äºå±è¿è¡éçè·åï¼æ¥ç对äºè·åéå¤±è´¥çæµç¨ï¼è¿å
¥ç¬¬ä¸å±å第åå±ççå¾
éåå¤çï¼èè¿äºå¤çæ¹å¼åä¾èµäºç¬¬äºå±çåºç¡æ°æ®æä¾å±ã
ä¸é¢æä»¬ä¼ä»æ´ä½å°ç»èï¼ä»æµç¨å°æ¹æ³éä¸åæ AQS æ¡æ¶ï¼ä¸»è¦åæè¿ç¨å¦ä¸ï¼

### 2.1 åçæ¦è§
AQS æ ¸å¿ææ³æ¯ï¼å¦æè¢«è¯·æ±çå
±äº«èµæºç©ºé²ï¼é£ä¹å°±å°å½å请æ±èµæºç线ç¨è®¾ç½®ä¸ºææçå·¥ä½çº¿ç¨ï¼å°å
±äº«èµæºè®¾ç½®ä¸ºéå®ç¶æï¼å¦æå
±äº«èµæºè¢«å ç¨ï¼å°±éè¦ä¸å®çé»å¡çå¾
å¤éæºå¶æ¥ä¿è¯éåé
ãè¿ä¸ªæºå¶ä¸»è¦ç¨çæ¯ CLH éåçåä½å®ç°çï¼å°ææ¶è·åä¸å°éç线ç¨å å
¥å°éåä¸ã
CLHï¼CraigãLandin and Hagersten éåï¼æ¯ååé¾è¡¨ï¼AQS ä¸çé忝 CLH åä½çèæååéåï¼FIFOï¼ï¼AQS æ¯éè¿å°æ¯æ¡è¯·æ±å
±äº«èµæºç线ç¨å°è£
æä¸ä¸ªèç¹æ¥å®ç°éçåé
ã
主è¦åçå¾å¦ä¸ï¼

AQS 使ç¨ä¸ä¸ª Volatile ç int ç±»åçæååéæ¥è¡¨ç¤ºåæ¥ç¶æï¼éè¿å
ç½®ç FIFO éåæ¥å®æèµæºè·åçæéå·¥ä½ï¼éè¿ CAS 宿坹 State å¼çä¿®æ¹ã
#### 2.1.1 AQS æ°æ®ç»æ
å
æ¥çä¸ AQS ä¸æåºæ¬çæ°æ®ç»æââNodeï¼Node å³ä¸ºä¸é¢ CLH åä½éåä¸çèç¹ã

è§£éä¸ä¸å ä¸ªæ¹æ³å屿§å¼çå«ä¹ï¼
| æ¹æ³å屿§å¼ | å«ä¹ |
| :----------- | :----------------------------------------------------------------------------------------------- |
| waitStatus | å½åèç¹å¨éåä¸çç¶æ |
| thread | 表示å¤äºè¯¥èç¹ççº¿ç¨ |
| prev | å驱æé |
| predecessor | è¿åå驱èç¹ï¼æ²¡æçè¯æåº npe |
| nextWaiter | æåä¸ä¸ä¸ªå¤äº CONDITION ç¶æçèç¹ï¼ç±äºæ¬ç¯æç« ä¸è®²è¿° Condition Queue éåï¼è¿ä¸ªæéä¸å¤ä»ç»ï¼ |
| next | åç»§æé |
线ç¨ä¸¤ç§éçæ¨¡å¼ï¼
| æ¨¡å¼ | å«ä¹ |
| :-------- | :----------------------------- |
| SHARED | 表示线ç¨ä»¥å
±äº«ç模å¼çå¾
é |
| EXCLUSIVE | è¡¨ç¤ºçº¿ç¨æ£å¨ä»¥ç¬å çæ¹å¼çå¾
é |
waitStatus æä¸é¢å 个æä¸¾å¼ï¼
| æä¸¾ | å«ä¹ |
| :-------- | :----------------------------------------------- |
| 0 | å½ä¸ä¸ª Node 被åå§åçæ¶åçé»è®¤å¼ |
| CANCELLED | 为 1ï¼è¡¨ç¤ºçº¿ç¨è·åéç请æ±å·²ç»åæ¶äº |
| CONDITION | 为-2ï¼è¡¨ç¤ºèç¹å¨çå¾
éåä¸ï¼èç¹çº¿ç¨çå¾
å¤é |
| PROPAGATE | 为-3ï¼å½å线ç¨å¤å¨ SHARED æ
åµä¸ï¼è¯¥å段æä¼ä½¿ç¨ |
| SIGNAL | 为-1ï¼è¡¨ç¤ºçº¿ç¨å·²ç»åå¤å¥½äºï¼å°±çèµæºéæ¾äº |
#### 2.1.2 åæ¥ç¶æ State
å¨äºè§£æ°æ®ç»æåï¼æ¥ä¸æ¥äºè§£ä¸ä¸ AQS çåæ¥ç¶æââStateãAQS ä¸ç»´æ¤äºä¸ä¸ªå为 state çåæ®µï¼æä¸ºåæ¥ç¶æï¼æ¯ç± Volatile 修饰çï¼ç¨äºå±ç¤ºå½å临çèµæºçè·éæ
åµã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private volatile int state;
```
ä¸é¢æä¾äºå 个访é®è¿ä¸ªåæ®µçæ¹æ³ï¼
| æ¹æ³å | æè¿° |
| :----------------------------------------------------------------- | :---------------------- |
| protected final int getState() | è·å State çå¼ |
| protected final void setState(int newState) | 设置 State çå¼ |
| protected final boolean compareAndSetState(int expect, int update) | ä½¿ç¨ CAS æ¹å¼æ´æ° State |
è¿å ä¸ªæ¹æ³é½æ¯ Final 修饰çï¼è¯´æåç±»ä¸æ æ³éåå®ä»¬ãæä»¬å¯ä»¥éè¿ä¿®æ¹ State åæ®µè¡¨ç¤ºçåæ¥ç¶ææ¥å®ç°å¤çº¿ç¨çç¬å 模å¼åå
±äº«æ¨¡å¼ï¼å éè¿ç¨ï¼ã


å¯¹äºæä»¬èªå®ä¹ç忥工å
·ï¼éè¦èªå®ä¹è·ååæ¥ç¶æåéæ¾ç¶æçæ¹å¼ï¼ä¹å°±æ¯ AQS æ¶æå¾ä¸ç第ä¸å±ï¼API å±ã
### 2.2 AQS éè¦æ¹æ³ä¸ ReentrantLock çå
³è
仿¶æå¾ä¸å¯ä»¥å¾ç¥ï¼AQS æä¾äºå¤§éç¨äºèªå®ä¹åæ¥å¨å®ç°ç Protected æ¹æ³ãèªå®ä¹åæ¥å¨å®ç°çç¸å
³æ¹æ³ä¹åªæ¯ä¸ºäºéè¿ä¿®æ¹ State åæ®µæ¥å®ç°å¤çº¿ç¨çç¬å æ¨¡å¼æè
å
±äº«æ¨¡å¼ãèªå®ä¹åæ¥å¨éè¦å®ç°ä»¥ä¸æ¹æ³ï¼ReentrantLock éè¦å®ç°çæ¹æ³å¦ä¸ï¼å¹¶ä¸æ¯å
¨é¨ï¼ï¼
| æ¹æ³å | æè¿° |
| :------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- |
| protected boolean isHeldExclusively() | è¯¥çº¿ç¨æ¯å¦æ£å¨ç¬å èµæºãåªæç¨å° Condition æéè¦å»å®ç°å®ã |
| protected boolean tryAcquire(int arg) | ç¬å æ¹å¼ãarg 为è·åéçæ¬¡æ°ï¼å°è¯è·åèµæºï¼æååè¿å Trueï¼å¤±è´¥åè¿å Falseã |
| protected boolean tryRelease(int arg) | ç¬å æ¹å¼ãarg ä¸ºéæ¾éçæ¬¡æ°ï¼å°è¯éæ¾èµæºï¼æååè¿å Trueï¼å¤±è´¥åè¿å Falseã |
| protected int tryAcquireShared(int arg) | å
±äº«æ¹å¼ãarg 为è·åéçæ¬¡æ°ï¼å°è¯è·åèµæºãè´æ°è¡¨ç¤ºå¤±è´¥ï¼0 表示æåï¼ä½æ²¡æå©ä½å¯ç¨èµæºï¼æ£æ°è¡¨ç¤ºæåï¼ä¸æå©ä½èµæºã |
| protected boolean tryReleaseShared(int arg) | å
±äº«æ¹å¼ãarg ä¸ºéæ¾éçæ¬¡æ°ï¼å°è¯éæ¾èµæºï¼å¦æéæ¾åå
许å¤éåç»çå¾
ç»ç¹è¿å Trueï¼å¦åè¿å Falseã |
ä¸è¬æ¥è¯´ï¼èªå®ä¹åæ¥å¨è¦ä¹æ¯ç¬å æ¹å¼ï¼è¦ä¹æ¯å
±äº«æ¹å¼ï¼å®ä»¬ä¹åªéå®ç° tryAcquire-tryReleaseãtryAcquireShared-tryReleaseShared ä¸çä¸ç§å³å¯ãAQS 乿¯æèªå®ä¹åæ¥å¨åæ¶å®ç°ç¬å åå
±äº«ä¸¤ç§æ¹å¼ï¼å¦ ReentrantReadWriteLockãReentrantLock æ¯ç¬å éï¼æä»¥å®ç°äº tryAcquire-tryReleaseã
以éå
¬å¹³é为ä¾ï¼è¿é主è¦éè¿°ä¸ä¸éå
¬å¹³éä¸ AQS ä¹é´æ¹æ³çå
³èä¹å¤ï¼å
·ä½æ¯ä¸å¤æ ¸å¿æ¹æ³çä½ç¨ä¼å¨æç« åé¢è¯¦ç»è¿è¡éè¿°ã

> ð ä¿®æ£ï¼åè§ï¼[issue#1761](https://github.com/Snailclimb/JavaGuide/issues/1761)ï¼: å¾ä¸çä¸å¤å°é误ï¼(AQS)CAS ä¿®æ¹å
±äº«èµæº State æåä¹ååºè¯¥æ¯è·åéæåï¼éå
¬å¹³éï¼ã
>
> 对åºçæºç å¦ä¸ï¼
>
> ```java
> final boolean nonfairTryAcquire(int acquires) {
> final Thread current = Thread.currentThread();//è·åå½å线ç¨
> int c = getState();
> if (c == 0) {
> if (compareAndSetState(0, acquires)) {//CASæ¢é
> setExclusiveOwnerThread(current);//设置å½å线ç¨ä¸ºç¬å 线ç¨
> return true;//æ¢éæå
> }
> }
> else if (current == getExclusiveOwnerThread()) {
> int nextc = c + acquires;
> if (nextc < 0) // overflow
> throw new Error("Maximum lock count exceeded");
> setState(nextc);
> return true;
> }
> return false;
> }
> ```
为äºå¸®å©å¤§å®¶çè§£ ReentrantLock å AQS ä¹é´æ¹æ³ç交äºè¿ç¨ï¼ä»¥éå
¬å¹³é为ä¾ï¼æä»¬å°å éåè§£éçäº¤äºæµç¨åç¬æåºæ¥å¼ºè°ä¸ä¸ï¼ä»¥ä¾¿äºå¯¹åç»å
容ççè§£ã

å éï¼
- éè¿ ReentrantLock çå éæ¹æ³ Lock è¿è¡å éæä½ã
- ä¼è°ç¨å°å
é¨ç±» Sync ç Lock æ¹æ³ï¼ç±äº Sync#lock æ¯æ½è±¡æ¹æ³ï¼æ ¹æ® ReentrantLock åå§åéæ©çå
¬å¹³éåéå
¬å¹³éï¼æ§è¡ç¸å
³å
é¨ç±»ç Lock æ¹æ³ï¼æ¬è´¨ä¸é½ä¼æ§è¡ AQS ç Acquire æ¹æ³ã
- AQS ç Acquire æ¹æ³ä¼æ§è¡ tryAcquire æ¹æ³ï¼ä½æ¯ç±äº tryAcquire éè¦èªå®ä¹åæ¥å¨å®ç°ï¼å æ¤æ§è¡äº ReentrantLock ä¸ç tryAcquire æ¹æ³ï¼ç±äº ReentrantLock æ¯éè¿å
¬å¹³éåéå
¬å¹³éå
é¨ç±»å®ç°ç tryAcquire æ¹æ³ï¼å æ¤ä¼æ ¹æ®éç±»åä¸åï¼æ§è¡ä¸åç tryAcquireã
- tryAcquire æ¯è·åéé»è¾ï¼è·å失败åï¼ä¼æ§è¡æ¡æ¶ AQS çåç»é»è¾ï¼è· ReentrantLock èªå®ä¹åæ¥å¨æ å
³ã
è§£éï¼
- éè¿ ReentrantLock çè§£éæ¹æ³ Unlock è¿è¡è§£éã
- Unlock ä¼è°ç¨å
é¨ç±» Sync ç Release æ¹æ³ï¼è¯¥æ¹æ³ç»§æ¿äº AQSã
- Release ä¸ä¼è°ç¨ tryRelease æ¹æ³ï¼tryRelease éè¦èªå®ä¹åæ¥å¨å®ç°ï¼tryRelease åªå¨ ReentrantLock ä¸ç Sync å®ç°ï¼å æ¤å¯ä»¥çåºï¼éæ¾éçè¿ç¨ï¼å¹¶ä¸åºåæ¯å¦ä¸ºå
¬å¹³éã
- éæ¾æååï¼ææå¤çç± AQS æ¡æ¶å®æï¼ä¸èªå®ä¹åæ¥å¨æ å
³ã
éè¿ä¸é¢çæè¿°ï¼å¤§æ¦å¯ä»¥æ»ç»åº ReentrantLock å éè§£éæ¶ API 屿 ¸å¿æ¹æ³çæ å°å
³ç³»ã

## 3 éè¿ ReentrantLock çè§£ AQS
ReentrantLock ä¸å
¬å¹³éåéå
¬å¹³éå¨åºå±æ¯ç¸åçï¼è¿é以éå
¬å¹³é为ä¾è¿è¡åæã
å¨éå
¬å¹³éä¸ï¼æä¸æ®µè¿æ ·ç代ç ï¼
```java
// java.util.concurrent.locks.ReentrantLock
static final class NonfairSync extends Sync {
...
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
...
}
```
çä¸ä¸è¿ä¸ª Acquire æ¯æä¹åçï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
```
åçä¸ä¸ tryAcquire æ¹æ³ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
```
å¯ä»¥çåºï¼è¿éåªæ¯ AQS çç®åå®ç°ï¼å
·ä½è·åéçå®ç°æ¹æ³æ¯ç±åèªçå
¬å¹³éåéå
¬å¹³éåç¬å®ç°çï¼ä»¥ ReentrantLock 为ä¾ï¼ãå¦æè¯¥æ¹æ³è¿åäº Trueï¼å说æå½å线ç¨è·åéæåï¼å°±ä¸ç¨å¾åæ§è¡äºï¼å¦æè·å失败ï¼å°±éè¦å å
¥å°çå¾
éåä¸ãä¸é¢ä¼è¯¦ç»è§£éçº¿ç¨æ¯ä½æ¶ä»¥åææ ·è¢«å å
¥è¿çå¾
éåä¸çã
### 3.1 线ç¨å å
¥çå¾
éå
#### 3.1.1 å å
¥éåçæ¶æº
彿§è¡ Acquire(1)æ¶ï¼ä¼éè¿ tryAcquire è·åéãå¨è¿ç§æ
åµä¸ï¼å¦æè·åé失败ï¼å°±ä¼è°ç¨ addWaiter å å
¥å°çå¾
éåä¸å»ã
#### 3.1.2 å¦ä½å å
¥éå
è·åé失败åï¼ä¼æ§è¡ addWaiter(Node.EXCLUSIVE)å å
¥çå¾
éåï¼å
·ä½å®ç°æ¹æ³å¦ä¸ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
```
主è¦çæµç¨å¦ä¸ï¼
- éè¿å½åç线ç¨å鿍¡å¼æ°å»ºä¸ä¸ªèç¹ã
- Pred æéæåå°¾èç¹ Tailã
- å° New ä¸ Node ç Prev æéæå Predã
- éè¿ compareAndSetTail æ¹æ³ï¼å®æå°¾èç¹ç设置ãè¿ä¸ªæ¹æ³ä¸»è¦æ¯å¯¹ tailOffset å Expect è¿è¡æ¯è¾ï¼å¦æ tailOffset ç Node å Expect ç Node å°åæ¯ç¸åçï¼é£ä¹è®¾ç½® Tail çå¼ä¸º Update çå¼ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
static {
try {
stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));
} catch (Exception ex) {
throw new Error(ex);
}
}
```
ä» AQS çéæä»£ç åå¯ä»¥çåºï¼é½æ¯è·åä¸ä¸ªå¯¹è±¡ç屿§ç¸å¯¹äºè¯¥å¯¹è±¡å¨å
åå½ä¸çåç§»éï¼è¿æ ·æä»¬å°±å¯ä»¥æ ¹æ®è¿ä¸ªåç§»éå¨å¯¹è±¡å
åå½ä¸æ¾å°è¿ä¸ªå±æ§ãtailOffset æçæ¯ tail 对åºçåç§»éï¼æä»¥è¿ä¸ªæ¶åä¼å° new åºæ¥ç Node 置为å½åéåçå°¾èç¹ãåæ¶ï¼ç±äºæ¯ååé¾è¡¨ï¼ä¹éè¦å°åä¸ä¸ªèç¹æåå°¾èç¹ã
- 妿 Pred æéæ¯ Nullï¼è¯´æçå¾
éå䏿²¡æå
ç´ ï¼ï¼æè
å½å Pred æéå Tail æåçä½ç½®ä¸åï¼è¯´æè¢«å«ç线ç¨å·²ç»ä¿®æ¹ï¼ï¼å°±éè¦çä¸ä¸ Enq çæ¹æ³ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
```
å¦ææ²¡æè¢«åå§åï¼éè¦è¿è¡åå§åä¸ä¸ªå¤´ç»ç¹åºæ¥ãä½è¯·æ³¨æï¼åå§åç头ç»ç¹å¹¶ä¸æ¯å½å线ç¨èç¹ï¼èæ¯è°ç¨äºæ åæé 彿°çèç¹ã妿ç»åäºåå§åæè
å¹¶å导è´éå䏿å
ç´ ï¼åä¸ä¹åçæ¹æ³ç¸åãå
¶å®ï¼addWaiter å°±æ¯ä¸ä¸ªå¨å端é¾è¡¨æ·»å å°¾èç¹çæä½ï¼éè¦æ³¨æçæ¯ï¼å端é¾è¡¨ç头ç»ç¹æ¯ä¸ä¸ªæ åæé 彿°ç头ç»ç¹ã
æ»ç»ä¸ä¸ï¼çº¿ç¨è·åéçæ¶åï¼è¿ç¨å¤§ä½å¦ä¸ï¼
1ã彿²¡æçº¿ç¨è·åå°éæ¶ï¼çº¿ç¨ 1 è·åéæåã
2ãçº¿ç¨ 2 ç³è¯·éï¼ä½æ¯éè¢«çº¿ç¨ 1 å æã

3ã妿åæçº¿ç¨è¦è·åéï¼ä¾æ¬¡å¨éåä¸å¾åæéå³å¯ã
åå°ä¸è¾¹ç代ç ï¼hasQueuedPredecessors æ¯å
¬å¹³éå 鿶夿çå¾
éå䏿¯å¦å卿æèç¹çæ¹æ³ã妿è¿å Falseï¼è¯´æå½å线ç¨å¯ä»¥äºåå
±äº«èµæºï¼å¦æè¿å Trueï¼è¯´æéåä¸å卿æèç¹ï¼å½å线ç¨å¿
é¡»å å
¥å°çå¾
éåä¸ã
```java
// java.util.concurrent.locks.ReentrantLock
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
}
```
çå°è¿éï¼æä»¬çè§£ä¸ä¸ h != t && ((s = h.next) == null || s.thread != Thread.currentThread());为ä»ä¹è¦å¤æç头ç»ç¹çä¸ä¸ä¸ªèç¹ï¼ç¬¬ä¸ä¸ªèç¹å¨åçæ°æ®æ¯ä»ä¹ï¼
> ååé¾è¡¨ä¸ï¼ç¬¬ä¸ä¸ªèç¹ä¸ºèèç¹ï¼å
¶å®å¹¶ä¸åå¨ä»»ä½ä¿¡æ¯ï¼åªæ¯å ä½ãçæ£ç第ä¸ä¸ªææ°æ®çèç¹ï¼æ¯å¨ç¬¬äºä¸ªèç¹å¼å§çãå½ h != t æ¶ï¼å¦æ(s = h.next) == nullï¼çå¾
éåæ£å¨æçº¿ç¨è¿è¡åå§åï¼ä½åªæ¯è¿è¡å°äº Tail æå Headï¼æ²¡æå° Head æå Tailï¼æ¤æ¶éå䏿å
ç´ ï¼éè¦è¿å Trueï¼è¿åå
·ä½è§ä¸è¾¹ä»£ç åæï¼ã 妿(s = h.next) != nullï¼è¯´ææ¤æ¶éåä¸è³å°æä¸ä¸ªææèç¹ãå¦ææ¤æ¶ s.thread == Thread.currentThread()ï¼è¯´æçå¾
éåç第ä¸ä¸ªææèç¹ä¸ç线ç¨ä¸å½å线ç¨ç¸åï¼é£ä¹å½åçº¿ç¨æ¯å¯ä»¥è·åèµæºçï¼å¦æ s.thread != Thread.currentThread()ï¼è¯´æçå¾
éåç第ä¸ä¸ªææèç¹çº¿ç¨ä¸å½å线ç¨ä¸åï¼å½å线ç¨å¿
é¡»å å
¥è¿çå¾
éåã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer#enq
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
```
èç¹å
¥é䏿¯ååæä½ï¼æä»¥ä¼åºç°çæç head != tailï¼æ¤æ¶ Tail æåæåä¸ä¸ªèç¹ï¼èä¸ Tail æå Headã妿 Head 没ææå Tailï¼å¯è§ 5ã6ã7 è¡ï¼ï¼è¿ç§æ
åµä¸ä¹éè¦å°ç¸å
³çº¿ç¨å å
¥éåä¸ãæä»¥è¿åä»£ç æ¯ä¸ºäºè§£å³æç«¯æ
åµä¸çå¹¶åé®é¢ã
#### 3.1.3 çå¾
éåä¸çº¿ç¨åºéåæ¶æº
åå°æåçæºç ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
```
ä¸æè§£éäº addWaiter æ¹æ³ï¼è¿ä¸ªæ¹æ³å
¶å®å°±æ¯æå¯¹åºç线ç¨ä»¥ Node çæ°æ®ç»æå½¢å¼å å
¥å°å端éåéï¼è¿åçæ¯ä¸ä¸ªå
å«è¯¥çº¿ç¨ç Nodeãèè¿ä¸ª Node ä¼ä½ä¸ºåæ°ï¼è¿å
¥å° acquireQueued æ¹æ³ä¸ãacquireQueued æ¹æ³å¯ä»¥å¯¹æéä¸ç线ç¨è¿è¡âè·éâæä½ã
æ»çæ¥è¯´ï¼ä¸ä¸ªçº¿ç¨è·åé失败äºï¼è¢«æ¾å
¥çå¾
éåï¼acquireQueued 伿æ¾å
¥éåä¸ç线ç¨ä¸æå»è·åéï¼ç´å°è·åæåæè
ä¸åéè¦è·åï¼ä¸æï¼ã
ä¸é¢æä»¬ä»â使¶åºéåï¼âåâå¦ä½åºéåï¼â两个æ¹åæ¥åæä¸ä¸ acquireQueued æºç ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
// æ è®°æ¯å¦æåæ¿å°èµæº
boolean failed = true;
try {
// æ è®°çå¾
è¿ç¨ä¸æ¯å¦ä¸æè¿
boolean interrupted = false;
// å¼å§èªæï¼è¦ä¹è·åéï¼è¦ä¹ä¸æ
for (;;) {
// è·åå½åèç¹çå驱èç¹
final Node p = node.predecessor();
// 妿pæ¯å¤´ç»ç¹ï¼è¯´æå½åèç¹å¨ç宿°æ®éåçé¦é¨ï¼å°±å°è¯è·åéï¼å«å¿äºå¤´ç»ç¹æ¯èèç¹ï¼
if (p == head && tryAcquire(arg)) {
// è·åéæåï¼å¤´æéç§»å¨å°å½ånode
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 说æp为头èç¹ä¸å½å没æè·åå°éï¼å¯è½æ¯éå
¬å¹³é被æ¢å äºï¼æè
æ¯pä¸ä¸ºå¤´ç»ç¹ï¼è¿ä¸ªæ¶åå°±è¦å¤æå½ånodeæ¯å¦è¦è¢«é»å¡ï¼è¢«é»å¡æ¡ä»¶ï¼å驱èç¹çwaitStatus为-1ï¼ï¼é²æ¢æ éå¾ªç¯æµªè´¹èµæºãå
·ä½ä¸¤ä¸ªæ¹æ³ä¸é¢ç»ç»åæ
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
```
注ï¼setHead æ¹æ³æ¯æå½åèç¹ç½®ä¸ºèèç¹ï¼ä½å¹¶æ²¡æä¿®æ¹ waitStatusï¼å ä¸ºå®æ¯ä¸ç´éè¦ç¨çæ°æ®ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer
// é å驱èç¹å¤æå½åçº¿ç¨æ¯å¦åºè¯¥è¢«é»å¡
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
// è·åå驱ç»ç¹çèç¹ç¶æ
int ws = pred.waitStatus;
// 说æå驱ç»ç¹å¤äºå¤éç¶æ
if (ws == Node.SIGNAL)
return true;
// éè¿æä¸¾å¼æä»¬ç¥éwaitStatus>0æ¯åæ¶ç¶æ
if (ws > 0) {
do {
// 循ç¯å忥æ¾åæ¶èç¹ï¼æåæ¶èç¹ä»éåä¸åé¤
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 设置åä»»èç¹çå¾
ç¶æä¸ºSIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
```
parkAndCheckInterrupt 主è¦ç¨äºæèµ·å½å线ç¨ï¼é»å¡è°ç¨æ ï¼è¿åå½å线ç¨çä¸æç¶æã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
```
ä¸è¿°æ¹æ³çæµç¨å¾å¦ä¸ï¼

ä»ä¸å¾å¯ä»¥çåºï¼è·³åºå½å循ç¯çæ¡ä»¶æ¯å½âåç½®èç¹æ¯å¤´ç»ç¹ï¼ä¸å½å线ç¨è·åéæåâã为äºé²æ¢å æ»å¾ªç¯å¯¼è´ CPU èµæºè¢«æµªè´¹ï¼æä»¬ä¼å¤æåç½®èç¹çç¶ææ¥å³å®æ¯å¦è¦å°å½åçº¿ç¨æèµ·ï¼å
·ä½æèµ·æµç¨ç¨æµç¨å¾è¡¨ç¤ºå¦ä¸ï¼shouldParkAfterFailedAcquire æµç¨ï¼ï¼

ä»éåä¸éæ¾èç¹ççèææ¶äºï¼é£ä¹åææ°é®é¢äºï¼
- shouldParkAfterFailedAcquire ä¸åæ¶èç¹æ¯æä¹çæçå¢ï¼ä»ä¹æ¶å伿ä¸ä¸ªèç¹ç waitStatus 设置为-1ï¼
- æ¯å¨ä»ä¹æ¶é´éæ¾èç¹éç¥å°è¢«æèµ·ç线ç¨å¢ï¼
### 3.2 CANCELLED ç¶æèç¹çæ
acquireQueued æ¹æ³ä¸ç Finally 代ç ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
...
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
...
failed = false;
...
}
...
} finally {
if (failed)
cancelAcquire(node);
}
}
```
éè¿ cancelAcquire æ¹æ³ï¼å° Node çç¶ææ 记为 CANCELLEDãæ¥ä¸æ¥ï¼æä»¬éè¡æ¥åæè¿ä¸ªæ¹æ³çåçï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void cancelAcquire(Node node) {
// å°æ æèç¹è¿æ»¤
if (node == null)
return;
// 设置该èç¹ä¸å
³èä»»ä½çº¿ç¨ï¼ä¹å°±æ¯èèç¹
node.thread = null;
Node pred = node.prev;
// éè¿å驱èç¹ï¼è·³è¿åæ¶ç¶æçnode
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// è·åè¿æ»¤åçå驱èç¹çåç»§èç¹
Node predNext = pred.next;
// æå½ånodeçç¶æè®¾ç½®ä¸ºCANCELLED
node.waitStatus = Node.CANCELLED;
// 妿å½åèç¹æ¯å°¾èç¹ï¼å°ä»åå¾åç第ä¸ä¸ªéåæ¶ç¶æçèç¹è®¾ç½®ä¸ºå°¾èç¹
// æ´æ°å¤±è´¥çè¯ï¼åè¿å
¥elseï¼å¦ææ´æ°æåï¼å°tailçåç»§èç¹è®¾ç½®ä¸ºnull
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
// 妿å½åèç¹ä¸æ¯headçåç»§èç¹ï¼1:夿å½åèç¹å驱èç¹çæ¯å¦ä¸ºSIGNALï¼2:妿䏿¯ï¼åæå驱èç¹è®¾ç½®ä¸ºSIGNALçæ¯å¦æå
// 妿1å2䏿ä¸ä¸ªä¸ºtrueï¼å夿å½åèç¹ççº¿ç¨æ¯å¦ä¸ºnull
// 妿ä¸è¿°æ¡ä»¶é½æ»¡è¶³ï¼æå½åèç¹çå驱èç¹çåç»§æéæåå½åèç¹çåç»§èç¹
if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
// 妿å½åèç¹æ¯headçåç»§èç¹ï¼æè
ä¸è¿°æ¡ä»¶ä¸æ»¡è¶³ï¼é£å°±å¤éå½åèç¹çåç»§èç¹
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
```
å½åçæµç¨ï¼
- è·åå½åèç¹çå驱èç¹ï¼å¦æå驱èç¹çç¶ææ¯ CANCELLEDï¼é£å°±ä¸ç´å¾åéåï¼æ¾å°ç¬¬ä¸ä¸ª waitStatus <= 0 çèç¹ï¼å°æ¾å°ç Pred èç¹åå½å Node å
³èï¼å°å½å Node 设置为 CANCELLEDã
- æ ¹æ®å½åèç¹çä½ç½®ï¼èè以ä¸ä¸ç§æ
åµï¼
(1) å½åèç¹æ¯å°¾èç¹ã
(2) å½åèç¹æ¯ Head çåç»§èç¹ã
(3) å½åèç¹ä¸æ¯ Head çåç»§èç¹ï¼ä¹ä¸æ¯å°¾èç¹ã
æ ¹æ®ä¸è¿°ç¬¬äºæ¡ï¼æä»¬æ¥åææ¯ä¸ç§æ
åµçæµç¨ã
å½åèç¹æ¯å°¾èç¹ã

å½åèç¹æ¯ Head çåç»§èç¹ã

å½åèç¹ä¸æ¯ Head çåç»§èç¹ï¼ä¹ä¸æ¯å°¾èç¹ã

éè¿ä¸é¢çæµç¨ï¼æä»¬å¯¹äº CANCELLED èç¹ç¶æç产çåååå·²ç»æäºå¤§è´çäºè§£ï¼ä½æ¯ä¸ºä»ä¹ææçåå齿¯å¯¹ Next æéè¿è¡äºæä½ï¼è没æå¯¹ Prev æéè¿è¡æä½å¢ï¼ä»ä¹æ
åµä¸ä¼å¯¹ Prev æéè¿è¡æä½ï¼
> æ§è¡ cancelAcquire çæ¶åï¼å½åèç¹çåç½®èç¹å¯è½å·²ç»ä»éåä¸åºå»äºï¼å·²ç»æ§è¡è¿ Try 代ç åä¸ç shouldParkAfterFailedAcquire æ¹æ³äºï¼ï¼å¦ææ¤æ¶ä¿®æ¹ Prev æéï¼æå¯è½ä¼å¯¼è´ Prev æåå¦ä¸ä¸ªå·²ç»ç§»é¤éåç Nodeï¼å æ¤è¿ååå Prev æéä¸å®å
¨ã shouldParkAfterFailedAcquire æ¹æ³ä¸ï¼ä¼æ§è¡ä¸é¢ç代ç ï¼å
¶å®å°±æ¯å¨å¤ç Prev æéãshouldParkAfterFailedAcquire æ¯è·åé失败çæ
åµä¸æä¼æ§è¡ï¼è¿å
¥è¯¥æ¹æ³åï¼è¯´æå
±äº«èµæºå·²è¢«è·åï¼å½åèç¹ä¹åçèç¹é½ä¸ä¼åºç°ååï¼å æ¤è¿ä¸ªæ¶ååæ´ Prev æéæ¯è¾å®å
¨ã
>
> ```java
> do {
> node.prev = pred = pred.prev;
> } while (pred.waitStatus > 0);
> ```
### 3.3 å¦ä½è§£é
æä»¬å·²ç»åæäºå éè¿ç¨ä¸çåºæ¬æµç¨ï¼æ¥ä¸æ¥å对解éçåºæ¬æµç¨è¿è¡åæãç±äº ReentrantLock å¨è§£éçæ¶åï¼å¹¶ä¸åºåå
¬å¹³éåéå
¬å¹³éï¼æä»¥æä»¬ç´æ¥çè§£éçæºç ï¼
```java
// java.util.concurrent.locks.ReentrantLock
public void unlock() {
sync.release(1);
}
```
å¯ä»¥çå°ï¼æ¬è´¨éæ¾éçå°æ¹ï¼æ¯éè¿æ¡æ¶æ¥å®æçã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
```
å¨ ReentrantLock éé¢çå
¬å¹³éåéå
¬å¹³éçç¶ç±» Sync å®ä¹äºå¯éå
¥éçéæ¾éæºå¶ã
```java
// java.util.concurrent.locks.ReentrantLock.Sync
// æ¹æ³è¿åå½å鿝䏿¯æ²¡æè¢«çº¿ç¨ææ
protected final boolean tryRelease(int releases) {
// åå°å¯éå
¥æ¬¡æ°
int c = getState() - releases;
// å½å线ç¨ä¸æ¯ææéç线ç¨ï¼æåºå¼å¸¸
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 妿ææçº¿ç¨å
¨é¨éæ¾ï¼å°å½åç¬å éææçº¿ç¨è®¾ç½®ä¸ºnullï¼å¹¶æ´æ°state
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
```
æä»¬æ¥è§£éä¸è¿°æºç ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final boolean release(int arg) {
// ä¸è¾¹èªå®ä¹çtryRelease妿è¿åtrueï¼è¯´æè¯¥é没æè¢«ä»»ä½çº¿ç¨ææ
if (tryRelease(arg)) {
// è·å头ç»ç¹
Node h = head;
// 头ç»ç¹ä¸ä¸ºç©ºå¹¶ä¸å¤´ç»ç¹çwaitStatus䏿¯åå§åèç¹æ
åµï¼è§£é¤çº¿ç¨æèµ·ç¶æ
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
```
è¿éç夿æ¡ä»¶ä¸ºä»ä¹æ¯ h != null && h.waitStatus != 0ï¼
> h == null Head è¿æ²¡åå§åãåå§æ
åµä¸ï¼head == nullï¼ç¬¬ä¸ä¸ªèç¹å
¥éï¼Head ä¼è¢«åå§åä¸ä¸ªèæèç¹ãæä»¥è¯´ï¼è¿éå¦æè¿æ²¡æ¥å¾åå
¥éï¼å°±ä¼åºç° head == null çæ
åµã
>
> h != null && waitStatus == 0 表æåç»§èç¹å¯¹åºç线ç¨ä»å¨è¿è¡ä¸ï¼ä¸éè¦å¤éã
>
> h != null && waitStatus < 0 表æåç»§èç¹å¯è½è¢«é»å¡äºï¼éè¦å¤éã
åçä¸ä¸ unparkSuccessor æ¹æ³ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void unparkSuccessor(Node node) {
// è·å头ç»ç¹waitStatus
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
// è·åå½åèç¹çä¸ä¸ä¸ªèç¹
Node s = node.next;
// 妿ä¸ä¸ªèç¹æ¯nullæè
ä¸ä¸ªèç¹è¢«cancelledï¼å°±æ¾å°éåæå¼å§çécancelledçèç¹
if (s == null || s.waitStatus > 0) {
s = null;
// å°±ä»å°¾é¨èç¹å¼å§æ¾ï¼å°éé¦ï¼æ¾å°éå第ä¸ä¸ªwaitStatus<0çèç¹ã
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
// 妿å½åèç¹çä¸ä¸ªèç¹ä¸ä¸ºç©ºï¼èä¸ç¶æ<=0ï¼å°±æå½åèç¹unpark
if (s != null)
LockSupport.unpark(s.thread);
}
```
为ä»ä¹è¦ä»åå¾åæ¾ç¬¬ä¸ä¸ªé Cancelled çèç¹å¢ï¼åå å¦ä¸ã
ä¹åç addWaiter æ¹æ³ï¼
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
```
æä»¬ä»è¿éå¯ä»¥çå°ï¼èç¹å
¥é并䏿¯ååæä½ï¼ä¹å°±æ¯è¯´ï¼node.prev = pred; compareAndSetTail(pred, node) è¿ä¸¤ä¸ªå°æ¹å¯ä»¥çä½ Tail å
¥éçååæä½ï¼ä½æ¯æ¤æ¶ pred.next = node;è¿æ²¡æ§è¡ï¼å¦æè¿ä¸ªæ¶åæ§è¡äº unparkSuccessor æ¹æ³ï¼å°±æ²¡åæ³ä»åå¾åæ¾äºï¼æä»¥éè¦ä»åå¾åæ¾ãè¿æä¸ç¹åå ï¼å¨äº§ç CANCELLED ç¶æèç¹çæ¶åï¼å
æå¼çæ¯ Next æéï¼Prev æéå¹¶æªæå¼ï¼å æ¤ä¹æ¯å¿
é¡»è¦ä»åå¾åéåæè½å¤éåå®å
¨é¨ç Nodeã
ç»¼ä¸æè¿°ï¼å¦ææ¯ä»åå¾åæ¾ï¼ç±äºæç«¯æ
åµä¸å
¥éçéååæä½å CANCELLED èç¹äº§çè¿ç¨ä¸æå¼ Next æéçæä½ï¼å¯è½ä¼å¯¼è´æ æ³éåææçèç¹ãæä»¥ï¼å¤é对åºç线ç¨åï¼å¯¹åºç线ç¨å°±ä¼ç»§ç»å¾ä¸æ§è¡ãç»§ç»æ§è¡ acquireQueued æ¹æ³ä»¥åï¼ä¸æå¦ä½å¤çï¼
### 3.4 䏿æ¢å¤åçæ§è¡æµç¨
å¤éåï¼ä¼æ§è¡ return Thread.interrupted();ï¼è¿ä¸ªå½æ°è¿åçæ¯å½åæ§è¡çº¿ç¨çä¸æç¶æï¼å¹¶æ¸
é¤ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
```
ååå° acquireQueued 代ç ï¼å½ parkAndCheckInterrupt è¿å True æè
False çæ¶åï¼interrupted çå¼ä¸åï¼ä½é½ä¼æ§è¡ä¸æ¬¡å¾ªç¯ã妿è¿ä¸ªæ¶åè·åéæåï¼å°±ä¼æå½å interrupted è¿åã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
```
妿 acquireQueued 为 Trueï¼å°±ä¼æ§è¡ selfInterrupt æ¹æ³ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
```
è¯¥æ¹æ³å
¶å®æ¯ä¸ºäºä¸æçº¿ç¨ãä½ä¸ºä»ä¹è·åäºé以åè¿è¦ä¸æçº¿ç¨å¢ï¼è¿é¨åå±äº Java æä¾çåä½å¼ä¸æç¥è¯å
å®¹ï¼æå
´è¶£åå¦å¯ä»¥æ¥é
ä¸ä¸ãè¿éç®åä»ç»ä¸ä¸ï¼
1. å½ä¸æçº¿ç¨è¢«å¤éæ¶ï¼å¹¶ä¸ç¥é被å¤éçåå ï¼å¯è½æ¯å½å线ç¨å¨çå¾
ä¸è¢«ä¸æï¼ä¹å¯è½æ¯éæ¾äºé以å被å¤éãå æ¤æä»¬éè¿ Thread.interrupted()æ¹æ³æ£æ¥ä¸ææ è®°ï¼è¯¥æ¹æ³è¿åäºå½å线ç¨çä¸æç¶æï¼å¹¶å°å½å线ç¨ç䏿æ è¯è®¾ç½®ä¸º Falseï¼ï¼å¹¶è®°å½ä¸æ¥ï¼å¦æåç°è¯¥çº¿ç¨è¢«ä¸æè¿ï¼å°±å䏿䏿¬¡ã
2. 线ç¨å¨çå¾
èµæºçè¿ç¨ä¸è¢«å¤éï¼å¤éåè¿æ¯ä¼ä¸æå°å»å°è¯è·åéï¼ç´å°æ¢å°é为æ¢ãä¹å°±æ¯è¯´ï¼å¨æ´ä¸ªæµç¨ä¸ï¼å¹¶ä¸ååºä¸æï¼åªæ¯è®°å½ä¸æè®°å½ãæåæ¢å°éè¿åäºï¼é£ä¹å¦æè¢«ä¸æè¿çè¯ï¼å°±éè¦è¡¥å
䏿¬¡ä¸æã
è¿éçå¤çæ¹å¼ä¸»è¦æ¯è¿ç¨çº¿ç¨æ± ä¸åºæ¬è¿ä½åå
Worder ä¸ç runWorkerï¼éè¿ Thread.interrupted()è¿è¡é¢å¤ç夿å¤çï¼æå
´è¶£çåå¦å¯ä»¥çä¸ ThreadPoolExecutor æºç ã
### 3.5 å°ç»
æä»¬å¨ 1.3 å°è䏿åºäºä¸äºé®é¢ï¼ç°å¨æ¥åçä¸ä¸ã
> Qï¼æä¸ªçº¿ç¨è·åé失败çåç»æµç¨æ¯ä»ä¹å¢ï¼
>
> Aï¼åå¨æç§æéçåæºå¶ï¼çº¿ç¨ç»§ç»çå¾
ï¼ä»ç¶ä¿çè·åéçå¯è½ï¼è·åéæµç¨ä»å¨ç»§ç»ã
>
> Qï¼æ¢ç¶è¯´å°äºæéçåæºå¶ï¼é£ä¹å°±ä¸å®ä¼ææç§éåå½¢æï¼è¿æ ·çé忝ä»ä¹æ°æ®ç»æå¢ï¼
>
> Aï¼æ¯ CLH åä½ç FIFO å端éåã
>
> Qï¼å¤äºæéçåæºå¶ä¸ç线ç¨ï¼ä»ä¹æ¶åå¯ä»¥ææºä¼è·åéå¢ï¼
>
> Aï¼å¯ä»¥è¯¦ç»çä¸ 2.3.1.3 å°èã
>
> Qï¼å¦æå¤äºæéçåæºå¶ä¸ç线ç¨ä¸ç´æ æ³è·åéï¼éè¦ä¸ç´çå¾
ä¹ï¼è¿æ¯æå«ççç¥æ¥è§£å³è¿ä¸é®é¢ï¼
>
> Aï¼çº¿ç¨æå¨èç¹çç¶æä¼åæåæ¶ç¶æï¼åæ¶ç¶æçèç¹ä¼ä»éåä¸éæ¾ï¼å
·ä½å¯è§ 2.3.2 å°èã
>
> Qï¼Lock 彿°éè¿ Acquire æ¹æ³è¿è¡å éï¼ä½æ¯å
·ä½æ¯å¦ä½å éçå¢ï¼
>
> Aï¼AQS ç Acquire ä¼è°ç¨ tryAcquire æ¹æ³ï¼tryAcquire ç±å个èªå®ä¹åæ¥å¨å®ç°ï¼éè¿ tryAcquire 宿å éè¿ç¨ã
## 4 AQS åºç¨
### 4.1 ReentrantLock çå¯éå
¥åºç¨
ReentrantLock çå¯éå
¥æ§æ¯ AQS å¾å¥½çåºç¨ä¹ä¸ï¼å¨äºè§£å®ä¸è¿°ç¥è¯ç¹ä»¥åï¼æä»¬å¾å®¹æå¾ç¥ ReentrantLock å®ç°å¯éå
¥çæ¹æ³ãå¨ ReentrantLock éé¢ï¼ä¸ç®¡æ¯å
¬å¹³éè¿æ¯éå
¬å¹³éï¼é½æä¸æ®µé»è¾ã
å
¬å¹³éï¼
```java
// java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire
if (c == 0) {
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
```
éå
¬å¹³éï¼
```java
// java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire
if (c == 0) {
if (compareAndSetState(0, acquires)){
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
```
ä»ä¸é¢è¿ä¸¤æ®µé½å¯ä»¥çå°ï¼æä¸ä¸ªåæ¥ç¶æ State æ¥æ§å¶æ´ä½å¯éå
¥çæ
åµãState æ¯ Volatile 修饰çï¼ç¨äºä¿è¯ä¸å®çå¯è§æ§åæåºæ§ã
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private volatile int state;
```
æ¥ä¸æ¥ç State è¿ä¸ªå段主è¦çè¿ç¨ï¼
1. State åå§åçæ¶å为 0ï¼è¡¨ç¤ºæ²¡æä»»ä½çº¿ç¨ææéã
2. å½æçº¿ç¨ææè¯¥éæ¶ï¼å¼å°±ä¼å¨åæ¥çåºç¡ä¸+1ï¼åä¸ä¸ªçº¿ç¨å¤æ¬¡è·å¾éæ¯ï¼å°±ä¼å¤æ¬¡+1ï¼è¿éå°±æ¯å¯éå
¥çæ¦å¿µã
3. è§£é乿¯å¯¹è¿ä¸ªå段-1ï¼ä¸ç´å° 0ï¼æ¤çº¿ç¨å¯¹ééæ¾ã
### 4.2 JUC ä¸çåºç¨åºæ¯
é¤äºä¸è¾¹ ReentrantLock çå¯éå
¥æ§çåºç¨ï¼AQS ä½ä¸ºå¹¶åç¼ç¨çæ¡æ¶ï¼ä¸ºå¾å¤å
¶ä»åæ¥å·¥å
·æä¾äºè¯å¥½çè§£å³æ¹æ¡ãä¸é¢ååºäº JUC ä¸çå ç§åæ¥å·¥å
·ï¼å¤§ä½ä»ç»ä¸ä¸ AQS çåºç¨åºæ¯ï¼
| 忥工å
· | 忥工å
·ä¸ AQS çå
³è |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ReentrantLock | ä½¿ç¨ AQS ä¿åéé夿æç次æ°ãå½ä¸ä¸ªçº¿ç¨è·åéæ¶ï¼ReentrantLock è®°å½å½åè·å¾éççº¿ç¨æ è¯ï¼ç¨äºæ£æµæ¯å¦éå¤è·åï¼ä»¥åé误线ç¨è¯å¾è§£éæä½æ¶å¼å¸¸æ
åµçå¤çã |
| Semaphore | ä½¿ç¨ AQS åæ¥ç¶ææ¥ä¿åä¿¡å·éçå½å计æ°ãtryRelease ä¼å¢å 计æ°ï¼acquireShared ä¼åå°è®¡æ°ã |
| CountDownLatch | ä½¿ç¨ AQS åæ¥ç¶ææ¥è¡¨ç¤ºè®¡æ°ã计æ°ä¸º 0 æ¶ï¼ææç Acquire æä½ï¼CountDownLatch ç await æ¹æ³ï¼æå¯ä»¥éè¿ã |
| ReentrantReadWriteLock | ä½¿ç¨ AQS åæ¥ç¶æä¸ç 16 ä½ä¿ååéææçæ¬¡æ°ï¼å©ä¸ç 16 ä½ç¨äºä¿å读éçæææ¬¡æ°ã |
| ThreadPoolExecutor | Worker å©ç¨ AQS åæ¥ç¶æå®ç°å¯¹ç¬å 线ç¨åéç设置ï¼tryAcquire å tryReleaseï¼ã |
### 4.3 èªå®ä¹åæ¥å·¥å
·
äºè§£ AQS åºæ¬åç以åï¼æç
§ä¸é¢æè¯´ç AQS ç¥è¯ç¹ï¼èªå·±å®ç°ä¸ä¸ªåæ¥å·¥å
·ã
```java
public class LeeLock {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire (int arg) {
return compareAndSetState(0, 1);
}
@Override
protected boolean tryRelease (int arg) {
setState(0);
return true;
}
@Override
protected boolean isHeldExclusively () {
return getState() == 1;
}
}
private Sync sync = new Sync();
public void lock () {
sync.acquire(1);
}
public void unlock () {
sync.release(1);
}
}
```
éè¿æä»¬èªå·±å®ä¹ç Lock 宿ä¸å®ç忥åè½ã
```java
public class LeeMain {
static int count = 0;
static LeeLock leeLock = new LeeLock();
public static void main (String[] args) throws InterruptedException {
Runnable runnable = new Runnable() {
@Override
public void run () {
try {
leeLock.lock();
for (int i = 0; i < 10000; i++) {
count++;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
leeLock.unlock();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
```
ä¸è¿°ä»£ç æ¯æ¬¡è¿è¡ç»æé½ä¼æ¯ 20000ãéè¿ç®åçå è¡ä»£ç å°±è½å®ç°åæ¥åè½ï¼è¿å°±æ¯ AQS ç强大ä¹å¤ã
## 5 æ»ç»
æä»¬æ¥å¸¸å¼åä¸ä½¿ç¨å¹¶åçåºæ¯å¤ªå¤ï¼ä½æ¯å¯¹å¹¶åå
é¨çåºæ¬æ¡æ¶åçäºè§£ç人å´ä¸å¤ãç±äºç¯å¹
åå ï¼æ¬æä»
ä»ç»äºå¯éå
¥é ReentrantLock çåçå AQS åçï¼å¸æè½å¤æä¸ºå¤§å®¶äºè§£ AQS å ReentrantLock ç忥å¨çâæ²é¨ç âã
## åèèµæ
- Lea D. The java. util. concurrent synchronizer framework\[J]. Science of Computer Programming, 2005, 58(3): 293-309.
- ãJava å¹¶åç¼ç¨å®æã
- [ä¸å¯ä¸è¯´ç Javaâéâäº](https://tech.meituan.com/2018/11/15/java-lock.html)