# Java éäº
* [Java éäº](#java-éäº)
* [Java éåç±»](#java-éåç±»)
* [çº¿ç¨æ¯å¦éè¦å¯¹èµæºå é](#çº¿ç¨æ¯å¦éè¦å¯¹èµæºå é)
* [æ²è§é](#æ²è§é)
* [ä¹è§é](#ä¹è§é)
* [两ç§éç使ç¨åºæ¯](#两ç§éç使ç¨åºæ¯)
* [ä¹è§éçå®ç°æ¹å¼](#ä¹è§éçå®ç°æ¹å¼)
* [çæ¬å·æºå¶](#çæ¬å·æºå¶)
* [CAS ç®æ³](#cas-ç®æ³)
* [ä¹è§éç缺ç¹](#ä¹è§éç缺ç¹)
* [ABA é®é¢](#aba-é®é¢)
* [循ç¯å¼é大](#循ç¯å¼é大)
* [CASä¸synchronizedçä½¿ç¨æ
æ¯](#casä¸synchronizedçä½¿ç¨æ
æ¯)
* [èµæºå·²è¢«éå®ï¼çº¿ç¨æ¯å¦é»å¡](#èµæºå·²è¢«éå®çº¿ç¨æ¯å¦é»å¡)
* [èªæéçæåºèæ¯](#èªæéçæåºèæ¯)
* [ä»ä¹æ¯èªæé](#ä»ä¹æ¯èªæé)
* [èªæéçåç](#èªæéçåç)
* [èªæéçä¼ç¼ºç¹](#èªæéçä¼ç¼ºç¹)
* [èªæéçå®ç°](#èªæéçå®ç°)
* [TicketLock](#ticketlock)
* [CLHLock](#clhlock)
* [MCSLock](#mcslock)
* [CLHLock å MCSLock](#clhlock-å-mcslock)
* [å¤ä¸ªçº¿ç¨å¹¶å访é®èµæº](#å¤ä¸ªçº¿ç¨å¹¶å访é®èµæº)
* [éç¶æçåç±»](#éç¶æçåç±»)
* [Java 对象头](#java-对象头)
* [Synchronizedé](#synchronizedé)
* [Monitor](#monitor)
* [éçåç±»åå
¶è§£é](#éçåç±»åå
¶è§£é)
* [æ é](#æ é)
* [ååé](#ååé)
* [è½»é级é](#è½»é级é)
* [éé级é](#éé级é)
* [éçå
¬å¹³æ§ä¸éå
¬å¹³æ§](#éçå
¬å¹³æ§ä¸éå
¬å¹³æ§)
* [éå
¬å¹³æ§çå®ç°](#éå
¬å¹³æ§çå®ç°)
* [ReentrantLock åºæ¬æ¦è¿°](#reentrantlock-åºæ¬æ¦è¿°)
* [ReentrantLock å¦ä½å®ç°éå
¬å¹³æ§](#reentrantlock-å¦ä½å®ç°éå
¬å¹³æ§)
* [æ ¹æ®éæ¯å¦å¯éå
¥è¿è¡åºå](#æ ¹æ®éæ¯å¦å¯éå
¥è¿è¡åºå)
* [å¯éå
¥é](#å¯éå
¥é)
* [ä¸å¯éå
¥é](#ä¸å¯éå
¥é)
* [å¤ä¸ªçº¿ç¨è½å¤å
±äº«å䏿é](#å¤ä¸ªçº¿ç¨è½å¤å
±äº«å䏿é)
* [ç¬å éåå
±äº«é](#ç¬å éåå
±äº«é)
## Java éåç±»
Java ä¸çéæå¾å¤ï¼å¯ä»¥æç
§ä¸åçåè½ãç§ç±»è¿è¡åç±»ï¼ä¸é¢æ¯æå¯¹ Java ä¸ä¸äºå¸¸ç¨éçåç±»ï¼å
æ¬ä¸äºåºæ¬çæ¦è¿°

* ä»çº¿ç¨æ¯å¦éè¦å¯¹èµæºå éå¯ä»¥å为 `æ²è§é` å `ä¹è§é`
* ä»èµæºå·²è¢«éå®ï¼çº¿ç¨æ¯å¦é»å¡å¯ä»¥å为 `èªæé`
* ä»å¤ä¸ªçº¿ç¨å¹¶å访é®èµæºï¼ä¹å°±æ¯ Synchronized å¯ä»¥å为 `æ é`ã`ååé`ã `è½»é级é` å `éé级é`
* ä»éçå
¬å¹³æ§è¿è¡åºåï¼å¯ä»¥å为`å
¬å¹³é` å `éå
¬å¹³é`
* 仿 ¹æ®éæ¯å¦éå¤è·åå¯ä»¥å为 `å¯éå
¥é` å `ä¸å¯éå
¥é`
* ä»é£ä¸ªå¤ä¸ªçº¿ç¨è½å¦è·åå䏿éå为 `å
±äº«é` å `æä»é`
ä¸é¢æä»¬ä¾æ¬¡å¯¹å个éçåç±»è¿è¡è¯¦ç»éè¿°ã
## çº¿ç¨æ¯å¦éè¦å¯¹èµæºå é
Java æç
§æ¯å¦å¯¹èµæºå éå为`ä¹è§é`å`æ²è§é`ï¼ä¹è§éåæ²è§é并䏿¯ä¸ç§çå®åå¨çéï¼èæ¯ä¸ç§è®¾è®¡ææ³ï¼ä¹è§éåæ²è§é对äºçè§£ Java å¤çº¿ç¨åæ°æ®åºæ¥è¯´è³å
³éè¦ï¼ä¸é¢å°±æ¥æ¢è®¨ä¸ä¸è¿ä¸¤ç§å®ç°æ¹å¼çåºå«åä¼ç¼ºç¹
### æ²è§é
`æ²è§é`æ¯ä¸ç§æ²è§ææ³ï¼å®æ»è®¤ä¸ºæåçæ
åµå¯è½ä¼åºç°ï¼å®è®¤ä¸ºæ°æ®å¾å¯è½ä¼è¢«å
¶ä»äººæä¿®æ¹ï¼æä»¥æ²è§éå¨æææ°æ®çæ¶åæ»ä¼æ`èµæº` æè
`æ°æ®` éä½ï¼è¿æ ·å
¶ä»çº¿ç¨æ³è¦è¯·æ±è¿ä¸ªèµæºçæ¶åå°±ä¼é»å¡ï¼ç´å°çå°æ²è§éæèµæºéæ¾ä¸ºæ¢ãä¼ ç»çå
³ç³»åæ°æ®åºé边就ç¨å°äºå¾å¤è¿ç§éæºå¶ï¼**æ¯å¦è¡éï¼è¡¨éçï¼è¯»éï¼åéçï¼é½æ¯å¨åæä½ä¹åå
ä¸éã**æ²è§éçå®ç°å¾å¾ä¾é æ°æ®åºæ¬èº«çéåè½å®ç°ã
Java ä¸ç `Synchronized` å `ReentrantLock` çç¬å é(æä»é)乿¯ä¸ç§æ²è§éææ³çå®ç°ï¼å 为 Synchronzied å ReetrantLock ä¸ç®¡æ¯å¦ææèµæºï¼å®é½ä¼å°è¯å»å éï¼çæèªå·±å¿ç±çå®è´è¢«å«äººæ¿èµ°ã
### ä¹è§é
ä¹è§éçææ³ä¸æ²è§éçææ³ç¸åï¼å®æ»è®¤ä¸ºèµæºåæ°æ®ä¸ä¼è¢«å«äººæä¿®æ¹ï¼æä»¥è¯»åä¸ä¼ä¸éï¼ä½æ¯ä¹è§éå¨è¿è¡åå
¥æä½çæ¶åä¼å¤æå½åæ°æ®æ¯å¦è¢«ä¿®æ¹è¿(å
·ä½å¦ä½å¤ææä»¬ä¸é¢å说)ãä¹è§éçå®ç°æ¹æ¡ä¸è¬æ¥è¯´æä¸¤ç§ï¼ `çæ¬å·æºå¶` å `CASå®ç°` ãä¹è§éå¤éç¨äºå¤åº¦çåºç¨ç±»åï¼è¿æ ·å¯ä»¥æé«ååéã
å¨Javaä¸`java.util.concurrent.atomic`å
ä¸é¢çåååé类就æ¯ä½¿ç¨äºä¹è§éçä¸ç§å®ç°æ¹å¼ CAS å®ç°çã
### 两ç§éç使ç¨åºæ¯
ä¸é¢ä»ç»äºä¸¤ç§éçåºæ¬æ¦å¿µï¼å¹¶æå°äºä¸¤ç§éçéç¨åºæ¯ï¼ä¸è¬æ¥è¯´ï¼æ²è§éä¸ä»
ä¼å¯¹åæä½å éè¿ä¼å¯¹è¯»æä½å éï¼ä¸ä¸ªå
¸åçæ²è§éè°ç¨ï¼
```mysql
select * from student where name="cxuan" for update
```
è¿æ¡ sql è¯å¥ä» Student 表ä¸éå name = "cxuan" çè®°å½å¹¶å¯¹å
¶å éï¼é£ä¹å
¶ä»åæä½åè¿ä¸ªäºå¡æäº¤ä¹åé½ä¸ä¼å¯¹è¿æ¡æ°æ®è¿è¡æä½ï¼èµ·å°äºç¬å åæä»çä½ç¨ã
æ²è§éå 为对读åé½å éï¼æä»¥å®çæ§è½æ¯è¾ä½ï¼å¯¹äºç°å¨äºèç½æå¡ç`ä¸é«`(髿§è½ãé«å¯ç¨ãé«å¹¶å)æ¥è¯´ï¼æ²è§éçå®ç°ç¨çè¶æ¥è¶å°äºï¼ä½æ¯ä¸è¬å¤è¯»çæ
åµä¸è¿æ¯éè¦ä½¿ç¨æ²è§éçï¼å 为è½ç¶å éçæ§è½æ¯è¾ä½ï¼ä½æ¯ä¹é»æ¢äºåä¹è§é䏿 ·ï¼éå°åä¸ä¸è´çæ
åµä¸ä¸ç´éè¯çæ¶é´ã
ç¸å¯¹èè¨ï¼ä¹è§éç¨äºè¯»å¤åå°çæ
åµï¼å³å¾å°åçå²çªçåºæ¯ï¼è¿æ ·å¯ä»¥çå»éçå¼éï¼å¢å ç³»ç»çååéã
ä¹è§éçéç¨åºæ¯æå¾å¤ï¼å
¸åçæ¯å¦è¯´ææ¬ç³»ç»ï¼æåè¦å¯¹ä¸ç¬éé¢åä¿®æ¹ï¼ä¸ºäºä¿è¯æ°æ®çåç¡®æ§å宿æ§ï¼ä½¿ç¨æ²è§ééä½æä¸ªæ°æ®åï¼åéå°å
¶ä»éè¦ä¿®æ¹æ°æ®çæä½ï¼é£ä¹æ¤æä½å°±æ æ³å®æéé¢çä¿®æ¹ï¼å¯¹äº§åæ¥è¯´æ¯ç¾é¾æ§çä¸å»ï¼ä½¿ç¨ä¹è§éççæ¬å·æºå¶è½å¤è§£å³è¿ä¸ªé®é¢ï¼æä»¬ä¸é¢è¯´ã
### ä¹è§éçå®ç°æ¹å¼
ä¹è§éä¸è¬æä¸¤ç§å®ç°æ¹å¼ï¼éç¨`çæ¬å·æºå¶` å `CASï¼Compare-and-Swapï¼å³æ¯è¾å¹¶æ¿æ¢ï¼`ç®æ³å®ç°ã
#### çæ¬å·æºå¶
çæ¬å·æºå¶æ¯å¨æ°æ®è¡¨ä¸å ä¸ä¸ä¸ª `version` åæ®µæ¥å®ç°çï¼è¡¨ç¤ºæ°æ®è¢«ä¿®æ¹ç次æ°ï¼å½æ§è¡åæä½å¹¶ä¸åå
¥æååï¼version = version + 1ï¼å½çº¿ç¨Aè¦æ´æ°æ°æ®æ¶ï¼å¨è¯»åæ°æ®çåæ¶ä¹ä¼è¯»å version å¼ï¼å¨æäº¤æ´æ°æ¶ï¼è¥åæè¯»åå°ç version å¼ä¸ºå½åæ°æ®åºä¸çversionå¼ç¸çæ¶ææ´æ°ï¼å¦åéè¯æ´æ°æä½ï¼ç´å°æ´æ°æåã
æä»¬ä»¥ä¸é¢çéèç³»ç»ä¸ºä¾ï¼æ¥ç®è¿°ä¸ä¸è¿ä¸ªè¿ç¨ã

* ææ¬ç³»ç»ä¸æä¸ä¸ªæ°æ®è¡¨ï¼è¡¨ä¸æä¸¤ä¸ªå段å嫿¯ `éé¢` å `version`ï¼éé¢ç屿§æ¯è½å¤å®æ¶ååï¼è version è¡¨ç¤ºçæ¯é颿¯æ¬¡åçååççæ¬ï¼ä¸è¬ççç¥æ¯ï¼å½éé¢åçæ¹åæ¶ï¼version éç¨éå¢ççç¥æ¯æ¬¡é½å¨ä¸ä¸ä¸ªçæ¬å·çåºç¡ä¸ + 1ã
* å¨äºè§£äºåºæ¬æ
åµååºæ¬ä¿¡æ¯ä¹åï¼æä»¬æ¥çä¸ä¸è¿ä¸ªè¿ç¨ï¼å
¬å¸æ¶å°å款åï¼éè¦æè¿ç¬é±æ¾å¨éåºä¸ï¼åå¦éåºä¸åæ100 å
é±
* ä¸é¢å¼å¯äºå¡ä¸ï¼å½ç·æåæ§è¡å款åå
¥æä½åï¼ä»ä¼å
æ¥ç(读)ä¸ä¸éåºä¸è¿æå¤å°é±ï¼æ¤æ¶è¯»å°éåºä¸æ 100 å
ï¼å¯ä»¥æ§è¡åæä½ï¼å¹¶ææ°æ®åºä¸ç鱿´æ°ä¸º 120 å
ï¼æäº¤äºå¡ï¼éåºä¸çé±ç± 100 -> 120ï¼versionççæ¬å·ç± 0 -> 1ã
* å¼å¯äºå¡äºï¼å¥³æåæ¶å°ç»åå·¥åå·¥èµç请æ±åï¼éè¦å
æ§è¡è¯»è¯·æ±ï¼æ¥çéåºä¸çé±è¿æå¤å°ï¼æ¤æ¶ççæ¬å·æ¯å¤å°ï¼ç¶åä»éåºä¸ååºåå·¥çå·¥èµè¿è¡åæ¾ï¼æäº¤äºå¡ï¼æååçæ¬ + 1ï¼æ¤æ¶çæ¬ç± 1 -> 2ã
**ä¸é¢ä¸¤ç§æ
嵿¯æä¹è§çæ
åµï¼ä¸é¢ç两个äºå¡é½æ¯é¡ºåºæ§è¡çï¼ä¹å°±æ¯äºå¡ä¸åäºå¡äºäºä¸å¹²æ°ï¼é£ä¹äºå¡è¦å¹¶è¡æ§è¡ä¼å¦ä½å¢ï¼**

* äºå¡ä¸å¼å¯ï¼ç·æåå
æ§è¡è¯»æä½ï¼ååºéé¢åçæ¬å·ï¼æ§è¡åæä½
```mysql
begin
update 表 set éé¢ = 120,version = version + 1 where éé¢ = 100 and version = 0
```
æ¤æ¶é颿¹ä¸º 120ï¼çæ¬å·ä¸º1ï¼äºå¡è¿æ²¡ææäº¤
äºå¡äºå¼å¯ï¼å¥³æåå
æ§è¡è¯»æä½ï¼ååºéé¢åçæ¬å·ï¼æ§è¡åæä½
```mysql
begin
update 表 set éé¢ = 50,version = version + 1 where éé¢ = 100 and version = 0
```
æ¤æ¶é颿¹ä¸º 50ï¼çæ¬å·å为 1ï¼äºå¡æªæäº¤
ç°å¨æäº¤äºå¡ä¸ï¼é颿¹ä¸º 120ï¼çæ¬å为1ï¼æäº¤äºå¡ãçæ³æ
åµä¸åºè¯¥å为 éé¢ = 50ï¼çæ¬å· = 2ï¼ä½æ¯å®é
ä¸äºå¡äº çæ´æ°æ¯å»ºç«å¨éé¢ä¸º 100 å çæ¬å·ä¸º 0 çåºç¡ä¸çï¼æä»¥äºå¡äºä¸ä¼æäº¤æåï¼åºè¯¥éæ°è¯»åéé¢åçæ¬å·ï¼å次è¿è¡åæä½ã
è¿æ ·ï¼å°±é¿å
äºå¥³æå ç¨åºäº version = 0 çæ§æ°æ®ä¿®æ¹çç»æè¦çç·æä½åæä½ç»æçå¯è½ã
#### CAS ç®æ³
**çç¥ä»£ç ï¼å®æ´ä»£ç 请åç
§ [çå®ä½ å°±åºè¯¥è½æç½çæ²è§éåä¹è§é](https://mp.weixin.qq.com/s?__biz=MzU2NDg0OTgyMA==&mid=2247484531&idx=1&sn=aca8142c1ca387ad276f0d2956a7e2c1&chksm=fc45f980cb32709667c1440b55ee6134437f6344dfd56ad1808ab36cd089b2da62b9c97cf9eb&token=24371561&lang=zh_CN#rd)**
CAS å³ `compare and swapï¼æ¯è¾ä¸äº¤æ¢ï¼`ï¼æ¯ä¸ç§æåçæ éç®æ³ãå³ä¸ä½¿ç¨éçæ
åµä¸å®ç°å¤çº¿ç¨ä¹é´çåé忥ï¼ä¹å°±æ¯å¨æ²¡æçº¿ç¨è¢«é»å¡çæ
åµä¸å®ç°åéçåæ¥ï¼æä»¥ä¹å«éé»å¡åæ¥ï¼Non-blocking Synchronization
Java ä» JDK1.5 å¼å§æ¯æï¼`java.util.concurrent` å
éæä¾äºå¾å¤é¢åå¹¶åç¼ç¨çç±»ï¼ä¹æä¾äº CAS ç®æ³çæ¯æï¼ä¸äºä»¥ `Atomic` 为å¼å¤´çä¸äºååç±»é½ä½¿ç¨ CAS ä½ä¸ºå
¶å®ç°æ¹å¼ã使ç¨è¿äºç±»å¨å¤æ ¸ CPU çæºå¨ä¸ä¼ææ¯è¾å¥½çæ§è½ã
å¦æè¦æè¯å®ä»¬çååæ§ï¼å¿
é¡»è¿è¡å éï¼ä½¿ç¨ `Synchronzied` æè
`ReentrantLock`ï¼æä»¬åé¢ä»ç»å®ä»¬æ¯æ²è§éçå®ç°ï¼æä»¬ç°å¨è®¨è®ºçæ¯ä¹è§éï¼é£ä¹ç¨åªç§æ¹å¼ä¿è¯å®ä»¬çååæ§å¢ï¼è¯·ç»§ç»å¾ä¸ç
CAS 䏿¶åä¸ä¸ªè¦ç´ ï¼
- éè¦è¯»åçå
åå¼ V
- è¿è¡æ¯è¾çå¼ A
- æåå
¥çæ°å¼ B
å½ä¸ä»
å½é¢æå¼Aåå
åå¼Vç¸åæ¶ï¼å°å
åå¼Vä¿®æ¹ä¸ºBï¼å¦åä»ä¹é½ä¸åã
æä»¬ä»¥ java.util.concurrent ä¸ç` AtomicInteger` 为ä¾ï¼çä¸ä¸å¨ä¸ç¨éçæ
åµä¸æ¯å¦ä½ä¿è¯çº¿ç¨å®å
¨ç
```java
public class AtomicCounter {
private AtomicInteger integer = new AtomicInteger();
public AtomicInteger getInteger() {
return integer;
}
public void setInteger(AtomicInteger integer) {
this.integer = integer;
}
public void increment(){
integer.incrementAndGet();
}
public void decrement(){
integer.decrementAndGet();
}
}
public class AtomicProducer extends Thread{
private AtomicCounter atomicCounter;
public AtomicProducer(AtomicCounter atomicCounter){
this.atomicCounter = atomicCounter;
}
@Override
public void run() {
for(int j = 0; j < AtomicTest.LOOP; j++) {
System.out.println("producer : " + atomicCounter.getInteger());
atomicCounter.increment();
}
}
}
public class AtomicConsumer extends Thread{
private AtomicCounter atomicCounter;
public AtomicConsumer(AtomicCounter atomicCounter){
this.atomicCounter = atomicCounter;
}
@Override
public void run() {
for(int j = 0; j < AtomicTest.LOOP; j++) {
System.out.println("consumer : " + atomicCounter.getInteger());
atomicCounter.decrement();
}
}
}
public class AtomicTest {
final static int LOOP = 10000;
public static void main(String[] args) throws InterruptedException {
AtomicCounter counter = new AtomicCounter();
AtomicProducer producer = new AtomicProducer(counter);
AtomicConsumer consumer = new AtomicConsumer(counter);
producer.start();
consumer.start();
producer.join();
consumer.join();
System.out.println(counter.getInteger());
}
}
```
ç»æµè¯å¯å¾ï¼ä¸ç®¡å¾ªç¯å¤å°æ¬¡æåçç»æé½æ¯0ï¼ä¹å°±æ¯å¤çº¿ç¨å¹¶è¡çæ
åµä¸ï¼ä½¿ç¨ AtomicInteger å¯ä»¥ä¿è¯çº¿ç¨å®å
¨æ§ã incrementAndGet å decrementAndGet 齿¯ååæ§æä½ã
### ä¹è§éç缺ç¹
ä»»ä½äºæ
齿¯æå©ä¹æå¼ï¼è½¯ä»¶è¡ä¸æ²¡æå®ç¾çè§£å³æ¹æ¡åªææä¼çè§£å³æ¹æ¡ï¼æä»¥ä¹è§é乿å®çå¼±ç¹å缺é·ï¼
#### ABA é®é¢
ABA é®é¢è¯´çæ¯ï¼å¦æä¸ä¸ªåéç¬¬ä¸æ¬¡è¯»åç弿¯ Aï¼åå¤å¥½éè¦å¯¹ A è¿è¡åæä½çæ¶åï¼åç°å¼è¿æ¯ Aï¼é£ä¹è¿ç§æ
åµä¸ï¼è½è®¤ä¸º A ç弿²¡æè¢«æ¹åè¿åï¼å¯ä»¥æ¯ç± A -> B -> A çè¿ç§æ
åµï¼ä½æ¯ AtomicInteger å´ä¸ä¼è¿ä¹è®¤ä¸ºï¼å®åªç¸ä¿¡å®çå°çï¼å®çå°çæ¯ä»ä¹å°±æ¯ä»ä¹ã
JDK 1.5 以åç `AtomicStampedReference `类就æä¾äºæ¤ç§è½åï¼å
¶ä¸ç `compareAndSet æ¹æ³`å°±æ¯é¦å
æ£æ¥å½åå¼ç¨æ¯å¦çäºé¢æå¼ç¨ï¼å¹¶ä¸å½åæ å¿æ¯å¦çäºé¢ææ å¿ï¼å¦æå
¨é¨ç¸çï¼å以ååæ¹å¼å°è¯¥å¼ç¨å该æ å¿çå¼è®¾ç½®ä¸ºç»å®çæ´æ°å¼ã
ä¹å¯ä»¥éç¨CASçä¸ä¸ªåç§DCASæ¥è§£å³è¿ä¸ªé®é¢ã
DCASï¼æ¯å¯¹äºæ¯ä¸ä¸ªVå¢å ä¸ä¸ªå¼ç¨çè¡¨ç¤ºä¿®æ¹æ¬¡æ°çæ 记符ãå¯¹äºæ¯ä¸ªVï¼å¦æå¼ç¨ä¿®æ¹äºä¸æ¬¡ï¼è¿ä¸ªè®¡æ°å¨å°±å 1ãç¶ååè¿ä¸ªåééè¦updateçæ¶åï¼å°±åæ¶æ£æ¥åéçå¼å计æ°å¨çå¼ã
#### 循ç¯å¼é大
æä»¬ç¥éä¹è§éå¨è¿è¡åæä½çæ¶åä¼å¤ææ¯å¦è½å¤åå
¥æåï¼å¦æåå
¥ä¸æåå°è§¦åçå¾
-> éè¯æºå¶ï¼è¿ç§æ
嵿¯ä¸ä¸ªèªæéï¼ç®åæ¥è¯´å°±æ¯éç¨äºçæå
è·åä¸å°ï¼è¿è¡çå¾
éè¯çéï¼å®ä¸éç¨äºé¿æè·åä¸å°éçæ
åµï¼å¦å¤ï¼èªæå¾ªç¯å¯¹äºæ§è½å¼éæ¯è¾å¤§ã
### CASä¸synchronizedçä½¿ç¨æ
æ¯
ç®åçæ¥è¯´ CAS éç¨äºåæ¯è¾å°çæ
åµä¸ï¼å¤è¯»åºæ¯ï¼å²çªä¸è¬è¾å°ï¼ï¼synchronized éç¨äºåæ¯è¾å¤çæ
åµä¸ï¼å¤ååºæ¯ï¼å²çªä¸è¬è¾å¤ï¼
- 对äºèµæºç«äºè¾å°ï¼çº¿ç¨å²çªè¾è½»ï¼çæ
åµï¼ä½¿ç¨ Synchronized 忥éè¿è¡çº¿ç¨é»å¡åå¤é忢以åç¨æ·æå
æ ¸æé´ç忢æä½é¢å¤æµªè´¹æ¶è cpu èµæºï¼è CAS åºäºç¡¬ä»¶å®ç°ï¼ä¸éè¦è¿å
¥å
æ ¸ï¼ä¸éè¦åæ¢çº¿ç¨ï¼æä½èªæå çè¾å°ï¼å æ¤å¯ä»¥è·å¾æ´é«çæ§è½ã
- 对äºèµæºç«äºä¸¥éï¼çº¿ç¨å²çªä¸¥éï¼çæ
åµï¼CAS èªæçæ¦ç伿¯è¾å¤§ï¼ä»è浪费æ´å¤ç CPU èµæºï¼æçä½äº synchronizedã
## èµæºå·²è¢«éå®ï¼çº¿ç¨æ¯å¦é»å¡
### èªæéçæåºèæ¯
ç±äºå¨å¤å¤çå¨ç¯å¢ä¸æäºèµæºçæéæ§ï¼ææ¶éè¦`äºæ¥è®¿é®(mutual exclusion)`ï¼è¿æ¶åå°±éè¦å¼å
¥éçæ¦å¿µï¼åªæè·åäºéççº¿ç¨æè½å¤å¯¹èµæºè¿è¡è®¿é®ï¼ç±äºå¤çº¿ç¨çæ ¸å¿æ¯CPUçæ¶é´åçï¼æä»¥å䏿¶å»åªè½æä¸ä¸ªçº¿ç¨è·åå°éãé£ä¹å°±é¢ä¸´ä¸ä¸ªé®é¢ï¼é£ä¹æ²¡æè·åå°éç线ç¨åºè¯¥æä¹åï¼
é常æä¸¤ç§å¤çæ¹å¼ï¼ä¸ç§æ¯æ²¡æè·åå°éç线ç¨å°±ä¸ç´å¾ªç¯çå¾
å¤æè¯¥èµæºæ¯å¦å·²ç»éæ¾éï¼è¿ç§éå«åèªæéï¼å®ä¸ç¨å°çº¿ç¨`é»å¡èµ·æ¥(NON-BLOCKING)`ï¼è¿æä¸ç§å¤çæ¹å¼å°±æ¯æèªå·±é»å¡èµ·æ¥ï¼çå¾
éæ°è°åº¦è¯·æ±ï¼è¿ç§å«å`äºæ¥é`ã
### ä»ä¹æ¯èªæé
èªæéçå®ä¹ï¼å½ä¸ä¸ªçº¿ç¨å°è¯å»è·åæä¸æéçæ¶åï¼å¦æè¿ä¸ªéæ¤æ¶å·²ç»è¢«å«äººè·å(å ç¨)ï¼é£ä¹æ¤çº¿ç¨å°±æ æ³è·åå°è¿æéï¼è¯¥çº¿ç¨å°ä¼çå¾
ï¼é´é䏿®µæ¶é´åä¼å次å°è¯è·åãè¿ç§éç¨å¾ªç¯å é -> çå¾
çæºå¶è¢«ç§°ä¸º`èªæé(spinlock)`ã

### èªæéçåç
èªæéçåçæ¯è¾ç®åï¼å¦æææéç线ç¨è½å¨çæ¶é´å
éæ¾éèµæºï¼é£ä¹é£äºçå¾
ç«äºéç线ç¨å°±ä¸éè¦åå
æ ¸æåç¨æ·æä¹é´ç忢è¿å
¥é»å¡ç¶æï¼å®ä»¬åªéè¦çä¸ç(èªæ)ï¼çå°ææéç线ç¨éæ¾éä¹åå³å¯è·åï¼è¿æ ·å°±é¿å
äºç¨æ·è¿ç¨åå
æ ¸åæ¢çæ¶èã
å ä¸ºèªæéé¿å
äºæä½ç³»ç»è¿ç¨è°åº¦å线ç¨åæ¢ï¼æä»¥èªæéé常éç¨å¨æ¶é´æ¯è¾ççæ
åµä¸ãç±äºè¿ä¸ªåå ï¼**æä½ç³»ç»çå
æ ¸ç»å¸¸ä½¿ç¨èªæé**ã使¯ï¼å¦æé¿æ¶é´ä¸éçè¯ï¼èªæéä¼é常èè´¹æ§è½ï¼å®é»æ¢äºå
¶ä»çº¿ç¨çè¿è¡åè°åº¦ãçº¿ç¨ææéçæ¶é´è¶é¿ï¼åææè¯¥éç线ç¨å°è¢« `OS(Operating System)` è°åº¦ç¨åºä¸æçé£é©è¶å¤§ã妿åç䏿æ
åµï¼é£ä¹å
¶ä»çº¿ç¨å°ä¿ææè½¬ç¶æ(åå¤å°è¯è·åé)ï¼èææè¯¥éç线ç¨å¹¶ä¸æç®éæ¾éï¼è¿æ ·å¯¼è´çæ¯ç»ææ¯æ éææ¨è¿ï¼ç´å°ææéç线ç¨å¯ä»¥å®æå¹¶éæ¾å®ä¸ºæ¢ã
è§£å³ä¸é¢è¿ç§æ
åµä¸ä¸ªå¾å¥½çæ¹å¼æ¯ç»èªæé设å®ä¸ä¸ªèªææ¶é´ï¼çæ¶é´ä¸å°ç«å³éæ¾èªæéãèªæéçç®çæ¯å çCPUèµæºä¸è¿è¡éæ¾ï¼çå°è·åéç«å³è¿è¡å¤çã使¯å¦ä½å»éæ©èªææ¶é´å¢ï¼å¦æèªææ§è¡æ¶é´å¤ªé¿ï¼ä¼æå¤§éç线ç¨å¤äºèªæç¶æå ç¨ CPU èµæºï¼è¿èä¼å½±åæ´ä½ç³»ç»çæ§è½ãå æ¤èªæç卿éçé¢å¤éè¦ï¼JDKå¨1.6 å¼å
¥äºéåºæ§èªæéï¼éåºæ§èªæéæå³çèªææ¶é´ä¸æ¯åºå®çäºï¼èæ¯ç±å䏿¬¡å¨åä¸ä¸ªéä¸çèªææ¶é´ä»¥å鿥æçç¶ææ¥å³å®ï¼åºæ¬è®¤ä¸ºä¸ä¸ªçº¿ç¨ä¸ä¸æåæ¢çæ¶é´æ¯æä½³çä¸ä¸ªæ¶é´ã
### èªæéçä¼ç¼ºç¹
èªæéå°½å¯è½çåå°çº¿ç¨çé»å¡ï¼è¿å¯¹äºéçç«äºä¸æ¿çï¼ä¸å ç¨éæ¶é´é常çç代ç åæ¥è¯´æ§è½è½å¤§å¹
度çæåï¼å ä¸ºèªæçæ¶èä¼å°äºçº¿ç¨é»å¡æèµ·åå¤éçæä½çæ¶èï¼è¿äºæä½ä¼å¯¼è´çº¿ç¨åç两次ä¸ä¸æåæ¢ï¼
使¯å¦æéçç«äºæ¿çï¼æè
ææéç线ç¨éè¦é¿æ¶é´å ç¨éæ§è¡åæ¥åï¼è¿æ¶åå°±ä¸éå使ç¨èªæéäºï¼å ä¸ºèªæéå¨è·åéåä¸ç´é½æ¯å ç¨ cpu åæ ç¨åï¼å ç XX ä¸ XXï¼åæ¶æå¤§é线ç¨å¨ç«äºä¸ä¸ªéï¼ä¼å¯¼è´è·åéçæ¶é´å¾é¿ï¼çº¿ç¨èªæçæ¶è大äºçº¿ç¨é»å¡æèµ·æä½çæ¶èï¼å
¶å®éè¦ cpu ç线ç¨åä¸è½è·åå° cpuï¼é æ cpu çæµªè´¹ãæä»¥è¿ç§æ
åµä¸æä»¬è¦å
³éèªæéã
### èªæéçå®ç°
ä¸é¢æä»¬ç¨Java ä»£ç æ¥å®ç°ä¸ä¸ªç®åçèªæé
```java
public class SpinLockTest {
private AtomicBoolean available = new AtomicBoolean(false);
public void lock(){
// å¾ªç¯æ£æµå°è¯è·åé
while (!tryLock()){
// doSomething...
}
}
public boolean tryLock(){
// å°è¯è·åéï¼æåè¿åtrueï¼å¤±è´¥è¿åfalse
return available.compareAndSet(false,true);
}
public void unLock(){
if(!available.compareAndSet(true,false)){
throw new RuntimeException("éæ¾é失败");
}
}
}
```
è¿ç§ç®åçèªæéæä¸ä¸ªé®é¢ï¼**æ æ³ä¿è¯å¤çº¿ç¨ç«äºçå
¬å¹³æ§**ã对äºä¸é¢ç SpinlockTestï¼å½å¤ä¸ªçº¿ç¨æ³è¦è·åéæ¶ï¼è°æå
å°`available`设为`false`è°å°±è½æå
è·å¾éï¼è¿å¯è½ä¼é ææäºçº¿ç¨ä¸ç´é½æªè·åå°éé æ`线ç¨é¥¥é¥¿`ãå°±åæä»¬ä¸è¯¾åèæ¥çè·åé£å ï¼ä¸çåèæ¥å°æ¤åå°éï¼é常æä»¬ä¼éåæéçæ¹å¼è§£å³è¿æ ·çé®é¢ï¼ç±»ä¼¼å°ï¼æä»¬æè¿ç§éå«**æéèªæé(QueuedSpinlock)**ãè®¡ç®æºç§å¦å®¶ä»¬ä½¿ç¨äºåç§æ¹å¼æ¥å®ç°æéèªæéï¼å¦TicketLockï¼MCSLockï¼CLHLockãæ¥ä¸æ¥æä»¬åå«å¯¹è¿å ç§éå个大è´çä»ç»ã
#### TicketLock
å¨è®¡ç®æºç§å¦é¢åä¸ï¼TicketLock æ¯ä¸ç§åæ¥æºå¶æéå®ç®æ³ï¼å®æ¯ä¸ç§èªæéï¼å®ä½¿ç¨`ticket` æ¥æ§å¶çº¿ç¨æ§è¡é¡ºåºã
å°±å票æ®éå管çç³»ç»ä¸æ ·ãé¢å
åºæè
æå¡æºæ(ä¾å¦é¶è¡)é½ä¼ä½¿ç¨è¿ç§æ¹å¼æ¥ä¸ºæ¯ä¸ªå
å°è¾¾ç顾客记å½å
¶å°è¾¾ç顺åºï¼èä¸ç¨æ¯æ¬¡é½è¿è¡æéãé常ï¼è¿ç§å°ç¹é½ä¼æä¸ä¸ªåé
å¨(å«å·å¨ï¼æå·å¨ççé½è¡)ï¼å
å°ç人éè¦å¨è¿ä¸ªæºå¨ä¸ååºèªå·±ç°å¨æéçå·ç ï¼è¿ä¸ªå·ç æ¯æç
§èªå¢ç顺åºè¿è¡çï¼æè¾¹è¿ä¼æä¸ä¸ªæ çæ¾ç¤ºçæ¯æ£å¨æå¡çæ å¿ï¼è¿é常æ¯ä»£è¡¨ç®åæ£å¨æå¡çéåå·ï¼å½åçå·ç 宿æå¡åï¼æ å¿ç伿¾ç¤ºä¸ä¸ä¸ªå·ç å¯ä»¥å»æå¡äºã
åä¸é¢ç³»ç»ä¸æ ·ï¼TicketLock æ¯åºäºå
è¿å
åº(FIFO) éåçæºå¶ãå®å¢å äºéçå
¬å¹³æ§ï¼å
¶è®¾è®¡ååå¦ä¸ï¼TicketLock ä¸æä¸¤ä¸ª int ç±»åçæ°å¼ï¼å¼å§é½æ¯0ï¼ç¬¬ä¸ä¸ªå¼æ¯`éåticket(éå票æ®)`ï¼ ç¬¬äºä¸ªå¼æ¯ `åºé(票æ®)`ãéåç¥¨æ®æ¯çº¿ç¨å¨éåä¸çä½ç½®ï¼èåºéç¥¨æ®æ¯ç°å¨ææéç票è¯çéåä½ç½®ãå¯è½æç¹æ¨¡ç³ä¸æ¸
ï¼ç®åæ¥è¯´ï¼**å°±æ¯éåç¥¨æ®æ¯ä½ å票å·çä½ç½®ï¼åºéç¥¨æ®æ¯ä½ è·ç¦»å«å·çä½ç½®**ãç°å¨åºè¯¥æç½ä¸äºäºå§ã
å½å«å·å«å°ä½ çæ¶åï¼ä¸è½æç¸åçå·ç åæ¶åä¸å¡ï¼å¿
é¡»åªæä¸ä¸ªäººå¯ä»¥å»åï¼åå®åï¼å«å·æºå«å°ä¸ä¸ä¸ªäººï¼è¿å°±å«å`ååæ§`ãä½ å¨åä¸å¡çæ¶åä¸è½è¢«å
¶ä»äººæå¹²æ°ï¼èä¸ä¸å¯è½ä¼æä¸¤ä¸ªææç¸åå·ç ç人å»åæ¶åä¸å¡ãç¶åï¼ä¸ä¸ä¸ªäººçèªå·±çå·æ¯å¦åå«å°çå·ç ä¿æä¸è´ï¼å¦æä¸è´çè¯ï¼é£ä¹å°±è½®å°ä½ å»åä¸å¡ï¼å¦ååªè½ç»§ç»çå¾
ã**ä¸é¢è¿ä¸ªæµç¨çå
³é®ç¹å¨äºï¼æ¯ä¸ªåä¸å¡ç人å¨åå®ä¸å¡ä¹åï¼ä»å¿
须丢å¼èªå·±çå·ç ï¼å«å·æºæè½ç»§ç»å«å°ä¸é¢ç人ï¼å¦æè¿ä¸ªäººæ²¡æä¸¢å¼è¿ä¸ªå·ç ï¼é£ä¹å
¶ä»äººåªè½ç»§ç»çå¾
**ãä¸é¢æ¥å®ç°ä¸ä¸è¿ä¸ªç¥¨æ®æéæ¹æ¡
```java
public class TicketLock {
// éå票æ®(å½åæéå·ç )
private AtomicInteger queueNum = new AtomicInteger();
// åºé票æ®(å½åéçå¾
å·ç )
private AtomicInteger dueueNum = new AtomicInteger();
// è·åéï¼å¦æè·åæåï¼è¿åå½å线ç¨çæéå·
public int lock(){
int currentTicketNum = dueueNum.incrementAndGet();
while (currentTicketNum != queueNum.get()){
// doSomething...
}
return currentTicketNum;
}
// éæ¾éï¼ä¼ å
¥å½åæéçå·ç
public void unLock(int ticketNum){
queueNum.compareAndSet(ticketNum,ticketNum + 1);
}
}
```
æ¯æ¬¡å«å·æºå¨å«å·çæ¶åï¼é½ä¼å¤æèªå·±æ¯ä¸æ¯è¢«å«çå·ï¼å¹¶ä¸æ¯ä¸ªäººå¨åå®ä¸å¡çæ¶åï¼å«å·æºæ ¹æ®å¨å½åå·ç çåºç¡ä¸ + 1ï¼è®©éåç»§ç»å¾åèµ°ã
使¯ä¸é¢è¿ä¸ªè®¾è®¡æ¯æé®é¢çï¼å 为è·å¾èªå·±çå·ç ä¹åï¼æ¯å¯ä»¥å¯¹å·ç è¿è¡æ´æ¹çï¼è¿å°±é æç³»ç»ç´ä¹±ï¼éä¸è½åæ¶éæ¾ãè¿æ¶åå°±éè¦æä¸ä¸ªè½ç¡®ä¿æ¯ä¸ªäººæä¼çèªå·±å·ç æéåä¸å¡çè§è²ï¼å¨å¾ç¥è¿ä¸ç¹ä¹åï¼æä»¬éæ°è®¾è®¡ä¸ä¸è¿ä¸ªé»è¾
```java
public class TicketLock2 {
// éå票æ®(å½åæéå·ç )
private AtomicInteger queueNum = new AtomicInteger();
// åºé票æ®(å½åéçå¾
å·ç )
private AtomicInteger dueueNum = new AtomicInteger();
private ThreadLocal ticketLocal = new ThreadLocal<>();
public void lock(){
int currentTicketNum = dueueNum.incrementAndGet();
// è·åéçæ¶åï¼å°å½å线ç¨çæéå·ä¿åèµ·æ¥
ticketLocal.set(currentTicketNum);
while (currentTicketNum != queueNum.get()){
// doSomething...
}
}
// éæ¾éï¼ä»æéç¼å²æ± ä¸å
public void unLock(){
Integer currentTicket = ticketLocal.get();
queueNum.compareAndSet(currentTicket,currentTicket + 1);
}
}
```
è¿æ¬¡å°±ä¸åéè¦è¿åå¼ï¼åä¸å¡çæ¶åï¼è¦å°å½åçè¿ä¸ä¸ªå·ç ç¼åèµ·æ¥ï¼å¨åå®ä¸å¡åï¼éè¦éæ¾ç¼åçè¿æ¡ç¥¨æ®ã
**缺ç¹**
TicketLock è½ç¶è§£å³äºå
¬å¹³æ§çé®é¢ï¼ä½æ¯å¤å¤çå¨ç³»ç»ä¸ï¼æ¯ä¸ªè¿ç¨/线ç¨å ç¨çå¤çå¨é½å¨è¯»ååä¸ä¸ªåéqueueNum ï¼æ¯æ¬¡è¯»åæä½é½å¿
é¡»å¨å¤ä¸ªå¤çå¨ç¼åä¹é´è¿è¡ç¼å忥ï¼è¿ä¼å¯¼è´ç¹éçç³»ç»æ»çº¿åå
åçæµéï¼å¤§å¤§éä½ç³»ç»æ´ä½çæ§è½ã
为äºè§£å³è¿ä¸ªé®é¢ï¼MCSLock å CLHLock åºè¿èçã
#### CLHLock
ä¸é¢è¯´å°TicketLock æ¯åºäºéåçï¼é£ä¹ CLHLock å°±æ¯åºäºé¾è¡¨è®¾è®¡çï¼CLHçåæäººæ¯ï¼Craigï¼Landin and Hagerstenï¼ç¨å®ä»¬åèªç忝å¼å¤´å½åãCLH æ¯ä¸ç§åºäºé¾è¡¨ç坿©å±ï¼é«æ§è½ï¼å
¬å¹³çèªæéï¼ç³è¯·çº¿ç¨åªè½å¨æ¬å°åéä¸èªæï¼å®ä¼ä¸æè½®è¯¢å驱çç¶æï¼å¦æåç°å驱鿾äºéå°±ç»æèªæã
```java
public class CLHLock {
public static class CLHNode{
private volatile boolean isLocked = true;
}
// å°¾é¨èç¹
private volatile CLHNode tail;
private static final ThreadLocal LOCAL = new ThreadLocal<>();
private static final AtomicReferenceFieldUpdater UPDATER =
AtomicReferenceFieldUpdater.newUpdater(CLHLock.class,CLHNode.class,"tail");
public void lock(){
// æ°å»ºèç¹å¹¶å°èç¹ä¸å½å线ç¨ä¿åèµ·æ¥
CLHNode node = new CLHNode();
LOCAL.set(node);
// å°æ°å»ºçèç¹è®¾ç½®ä¸ºå°¾é¨èç¹ï¼å¹¶è¿åæ§çèç¹ï¼ååæä½ï¼ï¼è¿éæ§çèç¹å®é
ä¸å°±æ¯å½åèç¹çå驱èç¹
CLHNode preNode = UPDATER.getAndSet(this,node);
if(preNode != null){
// å驱èç¹ä¸ä¸ºnull表示å½é被å
¶ä»çº¿ç¨å ç¨ï¼éè¿ä¸æè½®è¯¢å¤æå驱èç¹çéæ å¿ä½çå¾
å驱èç¹éæ¾é
while (preNode.isLocked){
}
preNode = null;
LOCAL.set(node);
}
// 妿ä¸åå¨å驱èç¹ï¼è¡¨ç¤ºè¯¥é没æè¢«å
¶ä»çº¿ç¨å ç¨ï¼åå½å线ç¨è·å¾é
}
public void unlock() {
// è·åå½å线ç¨å¯¹åºçèç¹
CLHNode node = LOCAL.get();
// 妿tailèç¹çäºnodeï¼åå°tailèç¹æ´æ°ä¸ºnullï¼åæ¶å°nodeçlockç¶æèä½falseï¼è¡¨ç¤ºå½å线ç¨éæ¾äºé
if (!UPDATER.compareAndSet(this, node, null)) {
node.isLocked = false;
}
node = null;
}
}
```
#### MCSLock
MCS Spinlock æ¯ä¸ç§åºäºé¾è¡¨ç坿©å±ã髿§è½ãå
¬å¹³çèªæéï¼ç³è¯·çº¿ç¨åªå¨æ¬å°åéä¸èªæï¼ç´æ¥å驱è´è´£éç¥å
¶ç»æèªæï¼ä»èæå¤§å°åå°äºä¸å¿
è¦çå¤çå¨ç¼ååæ¥çæ¬¡æ°ï¼éä½äºæ»çº¿åå
åçå¼éãMCS æ¥èªäºå
¶åæäººååçé¦åæ¯ï¼ John Mellor-Crummey å Michael Scottã
```java
public class MCSLock {
public static class MCSNode {
volatile MCSNode next;
volatile boolean isLocked = true;
}
private static final ThreadLocal NODE = new ThreadLocal<>();
// éå
@SuppressWarnings("unused")
private volatile MCSNode queue;
private static final AtomicReferenceFieldUpdater UPDATE =
AtomicReferenceFieldUpdater.newUpdater(MCSLock.class,MCSNode.class,"queue");
public void lock(){
// å建èç¹å¹¶ä¿åå°ThreadLocalä¸
MCSNode currentNode = new MCSNode();
NODE.set(currentNode);
// å°queue设置为å½åèç¹ï¼å¹¶ä¸è¿åä¹åçèç¹
MCSNode preNode = UPDATE.getAndSet(this, currentNode);
if (preNode != null) {
// 妿ä¹åèç¹ä¸ä¸ºnullï¼è¡¨ç¤ºéå·²ç»è¢«å
¶ä»çº¿ç¨ææ
preNode.next = currentNode;
// 循ç¯å¤æï¼ç´å°å½åèç¹çéæ å¿ä½ä¸ºfalse
while (currentNode.isLocked) {
}
}
}
public void unlock() {
MCSNode currentNode = NODE.get();
// next为nullè¡¨ç¤ºæ²¡ææ£å¨çå¾
è·åéç线ç¨
if (currentNode.next == null) {
// æ´æ°ç¶æå¹¶è®¾ç½®queue为null
if (UPDATE.compareAndSet(this, currentNode, null)) {
// 妿æåäºï¼è¡¨ç¤ºqueue==currentNode,å³å½åèç¹å颿²¡æèç¹äº
return;
} else {
// 妿䏿åï¼è¡¨ç¤ºqueue!=currentNode,å³å½åèç¹åé¢å¤äºä¸ä¸ªèç¹ï¼è¡¨ç¤ºæçº¿ç¨å¨çå¾
// 妿å½åèç¹çåç»èç¹ä¸ºnullï¼åéè¦çå¾
å
¶ä¸ä¸ºnullï¼åèå éæ¹æ³ï¼
while (currentNode.next == null) {
}
}
} else {
// 妿ä¸ä¸ºnullï¼è¡¨ç¤ºæçº¿ç¨å¨çå¾
è·åéï¼æ¤æ¶å°çå¾
线ç¨å¯¹åºçèç¹éç¶ææ´æ°ä¸ºfalseï¼åæ¶å°å½å线ç¨çåç»§èç¹è®¾ä¸ºnull
currentNode.next.isLocked = false;
currentNode.next = null;
}
}
}
```
#### CLHLock å MCSLock
- 齿¯åºäºé¾è¡¨ï¼ä¸åçæ¯CLHLockæ¯åºäºéå¼é¾è¡¨ï¼æ²¡æçæ£çåç»èç¹å±æ§ï¼MCSLockæ¯æ¾ç¤ºé¾è¡¨ï¼æä¸ä¸ªæååç»èç¹ç屿§ã
- å°è·åéç线ç¨ç¶æåå©èç¹(node)ä¿å,æ¯ä¸ªçº¿ç¨é½æä¸ä»½ç¬ç«çèç¹ï¼è¿æ ·å°±è§£å³äºTicketLockå¤å¤çå¨ç¼å忥çé®é¢ã
## å¤ä¸ªçº¿ç¨å¹¶å访é®èµæº
### éç¶æçåç±»
Java è¯è¨ä¸é¨é对 `synchronized` å
³é®å设置äºåç§ç¶æï¼å®ä»¬å嫿¯ï¼**æ éãååéãè½»é级éåéé级é**ï¼ä½æ¯å¨äºè§£è¿äºéä¹åè¿éè¦å
äºè§£ä¸ä¸ Java 对象头å Monitorã
### Java 对象头
æä»¬ç¥é synchronized æ¯æ²è§éï¼å¨æä½åæ¥ä¹åéè¦ç»èµæºå éï¼è¿æéå°±æ¯å¯¹è±¡å¤´éé¢çï¼èJava å¯¹è±¡å¤´åæ¯ä»ä¹å¢ï¼æä»¬ä»¥ Hotspot èææºä¸ºä¾ï¼Hopspot 对象头主è¦å
æ¬ä¸¤é¨åæ°æ®ï¼`Mark Wordï¼æ è®°åæ®µï¼` å `class Pointerï¼ç±»åæéï¼`ã
**Mark Word**ï¼é»è®¤åå¨å¯¹è±¡çHashCodeï¼å代年é¾åéæ å¿ä½ä¿¡æ¯ãè¿äºä¿¡æ¯é½æ¯ä¸å¯¹è±¡èªèº«å®ä¹æ å
³çæ°æ®ï¼æä»¥Mark Word被设计æä¸ä¸ªéåºå®çæ°æ®ç»æä»¥ä¾¿å¨æå°ç空é´å
ååå¨å°½éå¤çæ°æ®ãå®ä¼æ ¹æ®å¯¹è±¡çç¶æå¤ç¨èªå·±çåå¨ç©ºé´ï¼ä¹å°±æ¯è¯´å¨è¿è¡æé´Mark Wordéåå¨çæ°æ®ä¼éçéæ å¿ä½çååèååã
**class Point**ï¼å¯¹è±¡æåå®çç±»å
æ°æ®çæéï¼èææºéè¿è¿ä¸ªæéæ¥ç¡®å®è¿ä¸ªå¯¹è±¡æ¯åªä¸ªç±»çå®ä¾ã
å¨32ä½èææºå64ä½èææºç Mark Word æå ç¨çåè大å°ä¸ä¸æ ·ï¼32ä½èææºç Mark Word å class Pointer åå«å ç¨ 32bits çåèï¼è 64ä½èææºç Mark Word å class Pointer å ç¨äº64bits çåèï¼ä¸é¢æä»¬ä»¥ 32ä½èææºä¸ºä¾ï¼æ¥çä¸ä¸å
¶ Mark Word çåèå
·ä½æ¯å¦ä½åé
ç


ç¨ä¸æç¿»è¯è¿æ¥å°±æ¯

* æ ç¶æä¹å°±æ¯`æ é`çæ¶åï¼å¯¹è±¡å¤´å¼è¾ 25bit ç空é´ç¨æ¥åå¨å¯¹è±¡ç hashcode ï¼4bit ç¨äºåæ¾å代年é¾ï¼1bit ç¨æ¥åæ¾æ¯å¦ååéçæ è¯ä½ï¼2bit ç¨æ¥åæ¾éæ è¯ä½ä¸º01
* `ååé` ä¸ååæ´ç»ï¼è¿æ¯å¼è¾25bit ç空é´ï¼å
¶ä¸23bit ç¨æ¥åæ¾çº¿ç¨IDï¼2bit ç¨æ¥åæ¾ epochï¼4bit åæ¾å代年é¾ï¼1bit åæ¾æ¯å¦ååéæ è¯ï¼ 0表示æ éï¼1表示ååéï¼éçæ è¯ä½è¿æ¯01
* `è½»é级é`ä¸ç´æ¥å¼è¾ 30bit ç空é´åæ¾æåæ ä¸éè®°å½çæéï¼2bit åæ¾éçæ å¿ä½ï¼å
¶æ å¿ä½ä¸º00
* `éé级é`ä¸åè½»é级é䏿 ·ï¼30bit ç空é´ç¨æ¥åæ¾æåéé级éçæéï¼2bit åæ¾éçæ è¯ä½ï¼ä¸º11
* `GCæ è®°`å¼è¾30bit çå
å空é´å´æ²¡æå ç¨ï¼2bit 空é´åæ¾éæ å¿ä½ä¸º11ã
å
¶ä¸æ éåååéçéæ å¿ä½é½æ¯01ï¼åªæ¯å¨åé¢ç1bitåºåäºè¿æ¯æ éç¶æè¿æ¯ååéç¶æã
å
³äºä¸ºä»ä¹è¿ä¹åé
çå
åï¼æä»¬å¯ä»¥ä» `OpenJDK` ä¸ç[markOop.hpp](https://github.com/openjdk-mirror/jdk7u-hotspot/blob/50bdefc3afe944ca74c3093e7448d6b889cd20d1/src/share/vm/oops/markOop.hpp)ç±»ä¸çæä¸¾çª¥åºç«¯åª

æ¥è§£éä¸ä¸
* age_bits å°±æ¯æä»¬è¯´çåä»£åæ¶çæ è¯ï¼å ç¨4åè
* lock_bits æ¯éçæ å¿ä½ï¼å ç¨2个åè
* biased_lock_bits æ¯æ¯å¦ååéçæ è¯ï¼å ç¨1个åè
* max_hash_bits æ¯é对æ é计ç®çhashcode å ç¨åèæ°éï¼å¦ææ¯32ä½èææºï¼å°±æ¯ 32 - 4 - 2 -1 = 25 byteï¼å¦ææ¯64 ä½èææºï¼64 - 4 - 2 - 1 = 57 byteï¼ä½æ¯ä¼æ 25 åèæªä½¿ç¨ï¼æä»¥64ä½ç hashcode å ç¨ 31 byte
* hash_bits æ¯é对 64 ä½èææºæ¥è¯´ï¼å¦ææå¤§åèæ°å¤§äº 31ï¼åå31ï¼å¦ååçå®çåèæ°
* cms_bits æè§å¾åºè¯¥æ¯ä¸æ¯64ä½èææºå°±å ç¨ 0 byteï¼æ¯64ä½å°±å ç¨ 1byte
* epoch_bits å°±æ¯ epoch æå ç¨çåè大å°ï¼2åèã
### Synchronizedé
`synchronized`ç¨çéè®°å½æ¯åå¨Java对象头éçã
JVMåºäºè¿å
¥åéåº Monitor 对象æ¥å®ç°æ¹æ³åæ¥å代ç å忥ã代ç å忥æ¯ä½¿ç¨ monitorenter å monitorexit æä»¤å®ç°çï¼monitorenter æä»¤æ¯å¨ç¼è¯åæå
¥å°åæ¥ä»£ç åçå¼å§ä½ç½®ï¼è monitorexit æ¯æå
¥å°æ¹æ³ç»æå¤åå¼å¸¸å¤ãä»»ä½å¯¹è±¡é½æä¸ä¸ª monitor ä¸ä¹å
³èï¼å½ä¸ä¸ä¸ª monitor 被ææåï¼å®å°å¤äºéå®ç¶æã
æ ¹æ®èææºè§èçè¦æ±ï¼å¨æ§è¡ monitorenter æä»¤æ¶ï¼é¦å
è¦å»å°è¯è·å对象çéï¼å¦æè¿ä¸ªå¯¹è±¡æ²¡è¢«éå®ï¼æè
å½å线ç¨å·²ç»æ¥æäºé£ä¸ªå¯¹è±¡çéï¼æéç计æ°å¨å 1ï¼ç¸åºå°ï¼å¨æ§è¡ monitorexit æä»¤æ¶ä¼å°é计æ°å¨å1ï¼å½è®¡æ°å¨è¢«åå°0æ¶ï¼é就鿾äºã妿è·å对象é失败äºï¼é£å½å线ç¨å°±è¦é»å¡çå¾
ï¼ç´å°å¯¹è±¡é被å¦ä¸ä¸ªçº¿ç¨éæ¾ä¸ºæ¢ã
### Monitor
Synchronizedæ¯éè¿å¯¹è±¡å
é¨çä¸ä¸ªå«åçè§å¨éï¼monitorï¼æ¥å®ç°çï¼çè§å¨éæ¬è´¨åæ¯ä¾èµäºåºå±çæä½ç³»ç»ç Mutex Lockï¼äºæ¥éï¼æ¥å®ç°çãèæä½ç³»ç»å®ç°çº¿ç¨ä¹é´ç忢éè¦ä»ç¨æ·æè½¬æ¢å°æ ¸å¿æï¼è¿ä¸ªææ¬é常é«ï¼ç¶æä¹é´ç转æ¢éè¦ç¸å¯¹æ¯è¾é¿çæ¶é´ï¼è¿å°±æ¯ä¸ºä»ä¹ Synchronized æçä½çåå ãå æ¤ï¼è¿ç§ä¾èµäºæä½ç³»ç» Mutex Lock æå®ç°çéæä»¬ç§°ä¹ä¸º`éé级é`ã
Java SE 1.6为äºåå°è·å¾éåéæ¾é带æ¥çæ§è½æ¶èï¼å¼å
¥äº`ååé`å`è½»é级é`ï¼éä¸å
±æ4ç§ç¶æï¼çº§å«ä»ä½å°é«ä¾æ¬¡æ¯ï¼æ éç¶æãååéç¶æãè½»é级éç¶æåéé级éç¶æãéå¯ä»¥å级ä½ä¸è½é级ã
æä»¥éçç¶ææ»å
±æåç§ï¼æ éç¶æãååéãè½»é级éåéé级éãéçéçç«äºï¼éå¯ä»¥ä»ååéå级å°è½»é级éï¼åå级çéé级éï¼ä½æ¯éçå级æ¯ååçï¼ä¹å°±æ¯è¯´åªè½ä»ä½å°é«å级ï¼ä¸ä¼åºç°éçé级ï¼ãJDK 1.6ä¸é»è®¤æ¯å¼å¯ååéåè½»é级éçï¼æä»¬ä¹å¯ä»¥éè¿-XX:-UseBiasedLocking=falseæ¥ç¦ç¨ååéã
### éçåç±»åå
¶è§£é
å
æ¥ä¸ªå¤§ä½çæµç¨å¾æ¥æåä¸ä¸è¿ä¸ªè¿ç¨ï¼ç¶åä¸é¢æä»¬åå弿¥è¯´

#### æ é
`æ éç¶æ`ï¼æ é峿²¡æå¯¹èµæºè¿è¡éå®ï¼ææç线ç¨é½å¯ä»¥å¯¹åä¸ä¸ªèµæºè¿è¡è®¿é®ï¼ä½æ¯åªæä¸ä¸ªçº¿ç¨è½å¤æåä¿®æ¹èµæºã

æ éçç¹ç¹å°±æ¯å¨å¾ªç¯å
è¿è¡ä¿®æ¹æä½ï¼çº¿ç¨ä¼ä¸æçå°è¯ä¿®æ¹å
±äº«èµæºï¼ç´å°è½å¤æåä¿®æ¹èµæºå¹¶éåºï¼å¨æ¤è¿ç¨ä¸æ²¡æåºç°å²çªçåçï¼è¿å¾åæä»¬å¨ä¹åæç« ä¸ä»ç»ç CAS å®ç°ï¼CAS çåçååºç¨å°±æ¯æ éçå®ç°ãæ éæ æ³å
¨é¢ä»£æ¿æéï¼ä½æ é卿äºåºåä¸çæ§è½æ¯é常é«çã
#### ååé
HotSpot çä½è
ç»è¿ç ç©¶åç°ï¼å¤§å¤æ°æ
åµä¸ï¼éä¸ä»
ä¸åå¨å¤çº¿ç¨ç«äºï¼è¿åå¨éç±åä¸çº¿ç¨å¤æ¬¡è·å¾çæ
åµï¼ååéå°±æ¯å¨è¿ç§æ
åµä¸åºç°çï¼å®çåºç°æ¯ä¸ºäºè§£å³åªæå¨ä¸ä¸ªçº¿ç¨æ§è¡åæ¥æ¶æé«æ§è½ã

å¯ä»¥ä»å¯¹è±¡å¤´çåé
ä¸çå°ï¼ååéè¦æ¯æ éå¤äº`线ç¨ID` å `epoch`ï¼ä¸é¢æä»¬å°±æ¥æè¿°ä¸ä¸ååéçè·åè¿ç¨
**ååéè·åè¿ç¨**
1. é¦å
线ç¨è®¿é®åæ¥ä»£ç åï¼ä¼éè¿æ£æ¥å¯¹è±¡å¤´ Mark Word ç`éæ å¿ä½`夿ç®åéçç¶æï¼å¦ææ¯ 01ï¼è¯´æå°±æ¯æ éæè
ååéï¼ç¶ååæ ¹æ®`æ¯å¦ååé` çæ ç¤ºå¤ææ¯æ éè¿æ¯ååéï¼å¦ææ¯æ éæ
åµä¸ï¼æ§è¡ä¸ä¸æ¥
2. 线ç¨ä½¿ç¨ CAS æä½æ¥å°è¯å¯¹å¯¹è±¡å éï¼å¦æä½¿ç¨ CAS æ¿æ¢ ThreadID æåï¼å°±è¯´ææ¯ç¬¬ä¸æ¬¡ä¸éï¼é£ä¹å½å线ç¨å°±ä¼è·å¾å¯¹è±¡çååéï¼æ¤æ¶ä¼å¨å¯¹è±¡å¤´ç Mark Word ä¸è®°å½å½åçº¿ç¨ ID åè·åéçæ¶é´ epoch çä¿¡æ¯ï¼ç¶åæ§è¡åæ¥ä»£ç åã
>å
¨å±å®å
¨ç¹ï¼Safe Pointï¼ï¼å
¨å±å®å
¨ç¹ççè§£ä¼æ¶åå° C è¯è¨åºå±çä¸äºç¥è¯ï¼è¿éç®åçè§£ SafePoint æ¯ Java 代ç ä¸çä¸ä¸ªçº¿ç¨å¯è½æåæ§è¡çä½ç½®ã
çå°ä¸ä¸æ¬¡çº¿ç¨å¨è¿å
¥åéåºåæ¥ä»£ç åæ¶å°±ä¸éè¦è¿è¡ `CAS` æä½è¿è¡å éåè§£éï¼åªéè¦ç®å夿ä¸ä¸å¯¹è±¡å¤´ç Mark Word 䏿¯å¦åå¨çæåå½å线ç¨ç线ç¨IDï¼å¤æçæ å¿å½ç¶æ¯æ ¹æ®éçæ å¿ä½æ¥å¤æçãå¦æç¨æµç¨å¾æ¥è¡¨ç¤ºçè¯å°±æ¯ä¸é¢è¿æ ·

**å
³éååé**
ååéå¨Java 6 åJava 7 鿝é»è®¤`å¯ç¨`çãç±äºååéæ¯ä¸ºäºå¨åªæä¸ä¸ªçº¿ç¨æ§è¡åæ¥åæ¶æé«æ§è½ï¼å¦æä½ ç¡®å®åºç¨ç¨åºéææçéé常æ
åµä¸å¤äºç«äºç¶æï¼å¯ä»¥éè¿JVMåæ°å
³éååéï¼`-XX:-UseBiasedLocking=false`ï¼é£ä¹ç¨åºé»è®¤ä¼è¿å
¥è½»é级éç¶æã
**å
³äº epoch**
ååéçå¯¹è±¡å¤´ä¸æä¸ä¸ªè¢«ç§°ä¸º `epoch` çå¼ï¼å®ä½ä¸ºåå·®æææ§çæ¶é´æ³ã
#### è½»é级é
`è½»é级é`æ¯æå½å鿝ååéçæ¶åï¼èµæºè¢«å¦å¤ççº¿ç¨æè®¿é®ï¼é£ä¹ååéå°±ä¼å级为`è½»é级é`ï¼å
¶ä»çº¿ç¨ä¼éè¿`èªæ`çå½¢å¼å°è¯è·åéï¼ä¸ä¼é»å¡ï¼ä»èæé«æ§è½ï¼ä¸é¢æ¯è¯¦ç»çè·åè¿ç¨ã
**è½»é级éå éè¿ç¨**
1. ç´§æ¥çä¸ä¸æ¥ï¼å¦æ CAS æä½æ¿æ¢ ThreadID 没æè·åæåï¼æ§è¡ä¸ä¸æ¥
2. å¦æä½¿ç¨ CAS æä½æ¿æ¢ ThreadID 失败ï¼è¿æ¶å就忢å°å¦å¤ä¸ä¸ªçº¿ç¨çè§åº¦ï¼è¯´æè¯¥èµæºå·²è¢«åæ¥è®¿é®è¿ï¼è¿æ¶å就伿§è¡éçæ¤éæä½ï¼æ¤éååéï¼ç¶åçåææååéç线ç¨å°è¾¾`å
¨å±å®å
¨ç¹ï¼SafePointï¼`æ¶ï¼ä¼æååææååéç线ç¨ï¼ç¶å伿£æ¥åææååéçç¶æï¼å¦æå·²ç»éåºåæ¥ï¼å°±ä¼å¤éææååéç线ç¨ï¼æ§è¡ä¸ä¸æ¥
3. æ£æ¥å¯¹è±¡å¤´ä¸ç Mark Word è®°å½çæ¯å¦æ¯å½åçº¿ç¨ IDï¼å¦ææ¯ï¼æ§è¡åæ¥ä»£ç ï¼å¦æä¸æ¯ï¼æ§è¡**ååéè·åæµç¨** ç第2æ¥ã
å¦æç¨æµç¨è¡¨ç¤ºçè¯å°±æ¯ä¸é¢è¿æ ·ï¼å·²ç»å
å«ååéçè·åï¼

#### éé级é
éé级éçè·åæµç¨æ¯è¾å¤æï¼å°ä¼ä¼´ä»¬å好åå¤ï¼å
¶å®å¤çå é乿²¡é£ä¹éº»ç¦ï¼åµåµã
**éé级éçè·åæµç¨**
1. æ¥çä¸é¢ååéçè·åè¿ç¨ï¼ç±ååéå级为轻é级éï¼æ§è¡ä¸ä¸æ¥
2. ä¼å¨åææååéç线ç¨çæ ä¸åé
éè®°å½ï¼å°å¯¹è±¡å¤´ä¸ç Mark Word æ·è´å°åææååé线ç¨çè®°å½ä¸ï¼ç¶ååææååéç线ç¨è·å¾è½»é级éï¼ç¶åå¤éåææååéç线ç¨ï¼ä»å®å
¨ç¹å¤ç»§ç»æ§è¡ï¼æ§è¡å®æ¯åï¼æ§è¡ä¸ä¸æ¥ï¼å½åçº¿ç¨æ§è¡ç¬¬4æ¥
3. æ§è¡å®æ¯åï¼å¼å§è½»é级解éæä½ï¼è§£ééè¦å¤æä¸¤ä¸ªæ¡ä»¶
* å¤æå¯¹è±¡å¤´ä¸ç Mark Word ä¸éè®°å½æéæ¯å¦æåå½åæ ä¸è®°å½çæé

* æ·è´å¨å½å线ç¨éè®°å½ç Mark Word ä¿¡æ¯æ¯å¦ä¸å¯¹è±¡å¤´ä¸ç Mark Word ä¸è´ã
妿ä¸é¢ä¸¤ä¸ªå¤ææ¡ä»¶é½ç¬¦åçè¯ï¼å°±è¿è¡ééæ¾ï¼å¦æå
¶ä¸ä¸ä¸ªæ¡ä»¶ä¸ç¬¦åï¼å°±ä¼éæ¾éï¼å¹¶å¤èµ·çå¾
ç线ç¨ï¼è¿è¡æ°ä¸è½®çéç«äºã
4. å¨å½å线ç¨çæ ä¸åé
éè®°å½ï¼æ·è´å¯¹è±¡å¤´ä¸ç MarkWord å°å½å线ç¨çéè®°å½ä¸ï¼æ§è¡ CAS å éæä½ï¼ä¼æå¯¹è±¡å¤´ Mark Word ä¸éè®°å½æéæåå½å线ç¨éè®°å½ï¼å¦ææåï¼è·åè½»é级éï¼æ§è¡åæ¥ä»£ç ï¼ç¶åæ§è¡ç¬¬3æ¥ï¼å¦æä¸æåï¼æ§è¡ä¸ä¸æ¥
5. å½åçº¿ç¨æ²¡æä½¿ç¨ CAS æåè·åéï¼å°±ä¼èªæä¸ä¼å¿ï¼å次å°è¯è·åï¼å¦æå¨å¤æ¬¡èªæå°è¾¾ä¸éåè¿æ²¡æè·åå°éï¼é£ä¹è½»é级éå°±ä¼å级为 `éé级é`

å¦æç¨æµç¨å¾è¡¨ç¤ºæ¯è¿æ ·ç

## éçå
¬å¹³æ§ä¸éå
¬å¹³æ§
æä»¬ç¥éï¼å¨å¹¶åç¯å¢ä¸ï¼å¤ä¸ªçº¿ç¨éè¦å¯¹åä¸èµæºè¿è¡è®¿é®ï¼å䏿¶å»åªè½æä¸ä¸ªçº¿ç¨è½å¤è·åå°éå¹¶è¿è¡èµæºè®¿é®ï¼é£ä¹å©ä¸çè¿äºçº¿ç¨æä¹åå¢ï¼è¿å°±å¥½æ¯é£å æéæé¥ç模åï¼æå
å°è¾¾é£å çäººæ¥ææå
ä¹°é¥çæå©ï¼é£ä¹å©ä¸ç人就éè¦å¨ç¬¬ä¸ä¸ªäººå颿éï¼è¿æ¯çæ³çæ
åµï¼å³æ¯ä¸ªäººé½è½å¤ä¹°ä¸é¥ãé£ä¹ç°å®æ
嵿¯ï¼å¨ä½ æéçè¿ç¨ä¸ï¼å°±æä¸ªå«ä¸èå®ç人æ³èµ°æ·å¾ï¼æéæé¥ï¼å¦ææéçè¿ä¸ªäººå颿²¡æäººå¶æ¢ä»è¿ç§è¡ä¸ºï¼ä»å°±è½å¤é¡ºå©ä¹°ä¸é¥ï¼å¦ææäººå¶æ¢ï¼ä»å°±ä¹å¾å»éä¼å颿éã
å¯¹äºæ£å¸¸æéç人æ¥è¯´ï¼æ²¡æäººæéï¼æ¯ä¸ªäººé½å¨çå¾
æéæé¥çæºä¼ï¼é£ä¹è¿ç§æ¹å¼å¯¹æ¯ä¸ªäººæ¥è¯´é½æ¯å
¬å¹³çï¼å
æ¥åå°åãè¿ç§éä¹å«åå
¬å¹³éã

é£ä¹å妿éçè¿ä¸ªäººæåä¹°ä¸é¥å¹¶ä¸å¨ä¹°é¥çè¿ç¨ä¸ç®¡ææ²¡æäººå¶æ¢ä»ï¼ä»çè¿ç§è¡ä¸ºå¯¹æ£å¸¸æéç人æ¥è¯´é½æ¯ä¸å
¬å¹³çï¼è¿å¨éçä¸çä¸ä¹å«åéå
¬å¹³éã


é£ä¹æä»¬æ ¹æ®ä¸é¢çæè¿°å¯ä»¥å¾åºä¸é¢çç»è®º
**å
¬å¹³é**表示线ç¨è·åéçé¡ºåºæ¯æç
§çº¿ç¨å éçé¡ºåºæ¥åé
çï¼å³å
æ¥å
å¾çFIFOå
è¿å
åºé¡ºåºãè**éå
¬å¹³é**å°±æ¯ä¸ç§è·åéçæ¢å æºå¶ï¼æ¯éæºè·å¾éçï¼åå
¬å¹³éä¸ä¸æ ·çå°±æ¯å
æ¥çä¸ä¸å®å
å¾å°éï¼è¿ä¸ªæ¹å¼å¯è½é ææäºçº¿ç¨ä¸ç´æ¿ä¸å°éï¼ç»æä¹å°±æ¯ä¸å
¬å¹³çäºã
### éå
¬å¹³æ§çå®ç°
å¨ Java ä¸ï¼æä»¬ä¸è¬éè¿ `ReetrantLock` æ¥å®ç°éçå
¬å¹³æ§
æä»¬åå«éè¿ä¸¤ä¸ªä¾åæ¥è®²è§£ä¸ä¸éçå
¬å¹³æ§åéå
¬å¹³æ§
**éçå
¬å¹³æ§**
```java
public class MyFairLock extends Thread{
private ReentrantLock lock = new ReentrantLock(true);
public void fairLock(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "æ£å¨ææé");
}finally {
System.out.println(Thread.currentThread().getName() + "éæ¾äºé");
lock.unlock();
}
}
public static void main(String[] args) {
MyFairLock myFairLock = new MyFairLock();
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName() + "å¯å¨");
myFairLock.fairLock();
};
Thread[] thread = new Thread[10];
for(int i = 0;i < 10;i++){
thread[i] = new Thread(runnable);
}
for(int i = 0;i < 10;i++){
thread[i].start();
}
}
}
```
æä»¬å建äºä¸ä¸ª ReetrantLockï¼å¹¶ç»æé 彿°ä¼ äºä¸ä¸ª trueï¼æä»¬å¯ä»¥æ¥ç ReetrantLock çæé 彿°
```java
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
```
æ ¹æ® JavaDoc çæ³¨éå¯ç¥ï¼å¦ææ¯ true çè¯ï¼é£ä¹å°±ä¼å建ä¸ä¸ª ReentrantLock çå
¬å¹³éï¼ç¶åå¹¶å建ä¸ä¸ª `FairSync` ï¼FairSync å
¶å®æ¯ä¸ä¸ª `Sync` çå
é¨ç±»ï¼å®ç主è¦ä½ç¨æ¯åæ¥å¯¹è±¡ä»¥è·åå
¬å¹³éã

è Sync æ¯ ReentrantLock ä¸çå
é¨ç±»ï¼Sync ç»§æ¿ `AbstractQueuedSynchronizer` ç±»ï¼AbstractQueuedSynchronizer å°±æ¯æä»¬å¸¸è¯´ç AQS ï¼å®æ¯ JUCï¼java.util.concurrentï¼ ä¸æéè¦çä¸ä¸ªç±»ï¼éè¿å®æ¥å®ç°ç¬å éåå
±äº«éã
```java
abstract static class Sync extends AbstractQueuedSynchronizer {...}
```
ä¹å°±æ¯è¯´ï¼æä»¬æ fair åæ°è®¾ç½®ä¸º true ä¹åï¼å°±å¯ä»¥å®ç°ä¸ä¸ªå
¬å¹³éäºï¼æ¯è¿æ ·åï¼æä»¬åå°ç¤ºä¾ä»£ç ï¼æä»¬å¯ä»¥æ§è¡ä¸ä¸è¿æ®µä»£ç ï¼å®çè¾åºæ¯é¡ºåºè·åçï¼ç¢äºç¯å¹
çåå ï¼è¿éå°±æä¸è´´åºäºï¼,ä¹å°±æ¯è¯´æä»¬å建äºä¸ä¸ªå
¬å¹³é
**éçéå
¬å¹³æ§**
ä¸å
¬å¹³æ§ç¸å¯¹çå°±æ¯éå
¬å¹³æ§ï¼æä»¬éè¿è®¾ç½® `fair` åæ°ä¸º trueï¼ä¾¿å®ç°äºä¸ä¸ªå
¬å¹³éï¼ä¸ä¹ç¸å¯¹çï¼æä»¬æ fair åæ°è®¾ç½®ä¸º falseï¼æ¯ä¸æ¯å°±æ¯éå
¬å¹³éäºï¼ç¨äºå®è¯æä¸ä¸
```java
private ReentrantLock lock = new ReentrantLock(false);
```
å
¶ä»ä»£ç ä¸åï¼æä»¬æ§è¡ä¸ä¸ççè¾åºï¼é¨åè¾åºï¼
```java
Thread-1å¯å¨
Thread-4å¯å¨
Thread-1æ£å¨ææé
Thread-1éæ¾äºé
Thread-5å¯å¨
Thread-6å¯å¨
Thread-3å¯å¨
Thread-7å¯å¨
Thread-2å¯å¨
```
å¯ä»¥çå°ï¼çº¿ç¨çå¯å¨å¹¶æ²¡ææé¡ºåºè·åï¼å¯ä»¥çåºéå
¬å¹³é对éçè·åæ¯ä¹±åºçï¼å³æä¸ä¸ªæ¢å éçè¿ç¨ãä¹å°±æ¯è¯´ï¼æä»¬æ fair åæ°è®¾ç½®ä¸º false 便å®ç°äºä¸ä¸ªéå
¬å¹³éã
### ReentrantLock åºæ¬æ¦è¿°
ReentrantLock æ¯ä¸æ`å¯éå
¥é`ï¼ä¹æ¯ä¸æ`äºæ¥é`ï¼å®å
·æä¸ `synchronized` ç¸åçæ¹æ³åçè§å¨éçè¯ä¹ï¼ä½æ¯å®æ¯ synchronized ææ´å¤å¯æ©å±çåè½ã
ReentrantLock çå¯éå
¥æ§æ¯æå®å¯ä»¥ç±ä¸æ¬¡æåéå®ä½è¿æªè§£éççº¿ç¨æ¥æãå½åªæä¸ä¸ªçº¿ç¨å°è¯å éæ¶ï¼è¯¥çº¿ç¨è°ç¨ `lock()` æ¹æ³ä¼ç«å»è¿åæåå¹¶ç´æ¥è·åéã妿å½å线ç¨å·²ç»æ¥æè¿æéï¼è¿ä¸ªæ¹æ³ä¼ç«å»è¿åãå¯ä»¥ä½¿ç¨ `isHeldByCurrentThread` å `getHoldCount` è¿è¡æ£æ¥ã
è¿ä¸ªç±»çæé 彿°æ¥åå¯éæ©ç fairness åæ°ï¼å½ fairness 设置为 true æ¶ï¼å¨å¤çº¿ç¨äºå¤ºå°è¯å éæ¶ï¼éå¾åäºå¯¹çå¾
æ¶é´æé¿ç线ç¨è®¿é®ï¼è¿ä¹æ¯å
¬å¹³æ§çä¸ç§ä½ç°ãå¦åï¼éä¸è½ä¿è¯æ¯ä¸ªçº¿ç¨ç访é®é¡ºåºï¼ä¹å°±æ¯éå
¬å¹³éãä¸ä½¿ç¨é»è®¤è®¾ç½®çç¨åºç¸æ¯ï¼ä½¿ç¨è®¸å¤çº¿ç¨è®¿é®çå
¬å¹³éçç¨åºå¯è½ä¼æ¾ç¤º`è¾ä½`çæ»ä½ååéï¼å³è¾æ
¢ï¼éå¸¸è¦æ
¢å¾å¤ï¼ã使¯è·åéå¹¶ä¿è¯çº¿ç¨ä¸ä¼é¥¥é¥¿çæ¬¡æ°æ¯è¾å°ãæ 论å¦ä½è¯·æ³¨æï¼éçå
¬å¹³æ§ä¸è½ä¿è¯çº¿ç¨è°åº¦çå
¬å¹³æ§ãå æ¤ï¼ä½¿ç¨å
¬å¹³éçå¤çº¿ç¨ä¹ä¸å¯è½ä¼è¿ç»å¤æ¬¡è·å¾å®ï¼èå
¶ä»æ´»å¨çº¿ç¨æ²¡æè¿è¡ä¸å½åæªææè¯¥éãè¿ä¹æ¯`äºæ¥æ§` çä¸ç§ä½ç°ã
ä¹è¦æ³¨æç `tryLock()` æ¹æ³ä¸æ¯æå
¬å¹³æ§ã妿鿝å¯ä»¥è·åçï¼é£ä¹å³ä½¿å
¶ä»çº¿ç¨çå¾
ï¼å®ä»ç¶è½å¤è¿åæåã
æ¨è使ç¨ä¸é¢çä»£ç æ¥è¿è¡å éåè§£é
```java
class MyFairLock {
private final ReentrantLock lock = new ReentrantLock();
public void m() {
lock.lock();
try {
// ...
} finally {
lock.unlock()
}
}
}
```
ReentrantLock ééè¿åä¸çº¿ç¨æå¤æ¯æ2147483647个éå½éã å°è¯è¶
è¿æ¤éå¶ä¼å¯¼è´é宿¹æ³å¼åé误ã
### ReentrantLock å¦ä½å®ç°éå
¬å¹³æ§
æä»¬å¨ä¸é¢çç®è¿°ä¸æå°ï¼ReentrantLock æ¯å¯ä»¥å®ç°éçå
¬å¹³æ§çï¼é£ä¹åçæ¯ä»ä¹å¢ï¼ä¸é¢æä»¬éè¿å
¶æºç æ¥äºè§£ä¸ä¸ ReentrantLock æ¯å¦ä½å®ç°éçå
¬å¹³æ§ç
è·è¸ªå
¶æºç åç°ï¼è°ç¨ `Lock.lock()` æ¹æ³å
¶å®æ¯è°ç¨äº `sync` çå
é¨çæ¹æ³
```java
abstract void lock();
```
è sync æ¯æåºç¡ç忥æ§å¶ Lock çç±»ï¼å®æå
¬å¹³éåéå
¬å¹³éçå®ç°ãå®ç»§æ¿ `AbstractQueuedSynchronizer` å³ ä½¿ç¨ AQS ç¶æä»£è¡¨éææçæ°éã
lock æ¯æ½è±¡æ¹æ³æ¯éè¦è¢«åç±»å®ç°çï¼èç»§æ¿äº AQS çç±»ä¸»è¦æ

æä»¬å¯ä»¥çå°ï¼ææå®ç°äº AQS çç±»é½ä½äº JUC å
ä¸ï¼ä¸»è¦æäºç±»ï¼`ReentrantLock`ã`ReentrantReadWriteLock`ã`Semaphore`ã`CountDownLatch` å `ThreadPoolExecutor`ï¼å
¶ä¸ ReentrantLockãReentrantReadWriteLockãSemaphore é½å¯ä»¥å®ç°å
¬å¹³éåéå
¬å¹³éã
ä¸é¢æ¯å
¬å¹³é `FairSync` çç»§æ¿å
³ç³»

éå
¬å¹³éç`NonFairSync` çç»§æ¿å
³ç³»

ç±ç»§æ¿å¾å¯ä»¥çå°ï¼ä¸¤ä¸ªç±»çç»§æ¿å
³ç³»é½æ¯ç¸åçï¼æä»¬ä»æºç åç°ï¼å
¬å¹³éåéå
¬å¹³éçå®ç°å°±æ¯ä¸é¢è¿æ®µä»£ç çåºå«ï¼ä¸ä¸ç¯æç« æä»¬ä¼ä»åçè§åº¦åæä¸ä¸å
¬å¹³éåéå
¬å¹³éçå®ç°ï¼

éè¿ä¸å¾ä¸çæºä»£ç 对æ¯ï¼æä»¬å¯ä»¥ææ¾ççåºå
¬å¹³éä¸éå
¬å¹³éçlock()æ¹æ³å¯ä¸çåºå«å°±å¨äºå
¬å¹³éå¨è·ååæ¥ç¶ææ¶å¤äºä¸ä¸ªéå¶æ¡ä»¶ï¼`hasQueuedPredecessors()`ã
hasQueuedPredecessors() 乿¯ AQS ä¸çæ¹æ³ï¼å®ä¸»è¦æ¯ç¨æ¥ **æ¥è¯¢æ¯å¦æä»»ä½çº¿ç¨å¨çå¾
è·åéçæ¶é´æ¯å½å线ç¨é¿**ï¼ä¹å°±æ¯è¯´æ¯ä¸ªçå¾
线ç¨é½æ¯å¨ä¸ä¸ªéåä¸ï¼æ¤æ¹æ³å°±æ¯å¤æéåä¸å¨å½å线ç¨è·åéæ¶ï¼æ¯å¦æçå¾
éæ¶é´æ¯èªå·±è¿é¿çéåï¼å¦æå½å线ç¨ä¹åææéç线ç¨ï¼è¿å trueï¼å¦æå½å线ç¨ä½äºéåçå¼å¤´æéå为空ï¼è¿å falseã
综ä¸ï¼å
¬å¹³éå°±æ¯éè¿åæ¥é忥å®ç°å¤ä¸ªçº¿ç¨æç
§ç³è¯·éçé¡ºåºæ¥è·åéï¼ä»èå®ç°å
¬å¹³çç¹æ§ãéå
¬å¹³éå éæ¶ä¸èèæéçå¾
é®é¢ï¼ç´æ¥å°è¯è·åéï¼æä»¥åå¨åç³è¯·å´å
è·å¾éçæ
åµã
## æ ¹æ®éæ¯å¦å¯éå
¥è¿è¡åºå
### å¯éå
¥é
å¯éå
¥éå称为éå½éï¼æ¯æå¨åä¸ä¸ªçº¿ç¨å¨å¤å±æ¹æ³è·åéçæ¶åï¼åè¿å
¥è¯¥çº¿ç¨çå
屿¹æ³ä¼èªå¨è·åéï¼åæéå¯¹è±¡å¾æ¯åä¸ä¸ªå¯¹è±¡æè
classï¼ï¼ä¸ä¼å 为ä¹åå·²ç»è·åè¿è¿æ²¡éæ¾èé»å¡ãJava ä¸ `ReentrantLock` å`synchronized` 齿¯å¯éå
¥éï¼å¯éå
¥éçä¸ä¸ªä¼ç¹æ¯å¨ä¸å®ç¨åº¦ä¸å¯ä»¥é¿å
æ»éã
æä»¬å
æ¥ç䏿®µä»£ç æ¥è¯´æä¸ä¸ synchronized çå¯éå
¥æ§
```java
private synchronized void doSomething(){
System.out.println("doSomething...");
doSomethingElse();
}
private synchronized void doSomethingElse(){
System.out.println("doSomethingElse...");
}
```
å¨ä¸é¢è¿æ®µä»£ç ä¸ï¼æä»¬å¯¹ `doSomething()` å `doSomethingElse()` åå«ä½¿ç¨äº `synchronized` è¿è¡éå®ï¼doSomething() æ¹æ³ä¸è°ç¨äº doSomethingElse() æ¹æ³ï¼å 为 synchronized æ¯å¯éå
¥éï¼æä»¥åä¸ä¸ªçº¿ç¨å¨è°ç¨ doSomething() æ¹æ³æ¶ï¼ä¹è½å¤è¿å
¥ doSomethingElse() æ¹æ³ä¸ã
### ä¸å¯éå
¥é
妿 synchronized æ¯ä¸å¯éå
¥éçè¯ï¼é£ä¹å¨è°ç¨ doSomethingElse() æ¹æ³çæ¶åï¼å¿
é¡»æ doSomething() çé丢æï¼å®é
ä¸è¯¥å¯¹è±¡é已被å½åçº¿ç¨æææï¼ä¸æ æ³éæ¾ãæä»¥æ¤æ¶ä¼åºç°æ»éã
ä¹å°±æ¯è¯´ï¼ä¸å¯éå
¥éä¼é ææ»é
## å¤ä¸ªçº¿ç¨è½å¤å
±äº«å䏿é
### ç¬å éåå
±äº«é
ç¬å å¤åå
±äº«éä¸è¬å¯¹åº JDK æºç ç ReentrantLock å ReentrantReadWriteLock æºç æ¥ä»ç»ç¬å éåå
±äº«éã
ç¬å éåå«åæä»éï¼æ¯æéå¨å䏿¶å»åªè½è¢«ä¸ä¸ªçº¿ç¨æ¥æï¼å
¶ä»çº¿ç¨æ³è¦è®¿é®èµæºï¼å°±ä¼è¢«é»å¡ãJDK ä¸ synchronizedå JUC ä¸ Lock çå®ç°ç±»å°±æ¯äºæ¥éã
å
±äº«éæçæ¯éè½å¤è¢«å¤ä¸ªçº¿ç¨ææ¥æï¼å¦ææä¸ªçº¿ç¨å¯¹èµæºå ä¸å
±äº«éåï¼åå
¶ä»çº¿ç¨åªè½å¯¹èµæºåå å
±äº«éï¼ä¸è½å æå®éã**è·å¾å
±äº«éç线ç¨åªè½è¯»æ°æ®ï¼ä¸è½ä¿®æ¹æ°æ®**ã

æä»¬çå° ReentrantReadWriteLock æä¸¤æéï¼`ReadLock` å `WriteLock`ï¼ä¹å°±æ¯ä¸ä¸ªè¯»éä¸ä¸ªåéï¼åå¨ä¸èµ·å«å读åéãåè¿ä¸æ¥è§å¯å¯ä»¥åç° ReadLock å WriteLock æ¯é å
é¨ç±» Sync å®ç°çéãSync æ¯ç»§æ¿äº AQS åç±»çï¼AQS æ¯å¹¶åçæ ¹æ¬ï¼è¿ç§ç»æå¨CountDownLatchãReentrantLockãSemaphoreéé¢ä¹é½åå¨ã
å¨ ReentrantReadWriteLock éé¢ï¼è¯»éååéçé主ä½é½æ¯ Syncï¼ä½è¯»éååéçå éæ¹å¼ä¸ä¸æ ·ãè¯»éæ¯å
±äº«éï¼å鿝ç¬äº«éã读éçå
±äº«éå¯ä¿è¯å¹¶å读é叏髿ï¼è读åãå读ãååçè¿ç¨äºæ¥ï¼å 为读éåå鿝å离çãæä»¥ReentrantReadWriteLockçå¹¶åæ§ç¸æ¯ä¸è¬çäºæ¥éæäºå¾å¤§æåã

