# JUC
## è¿ç¨
### æ¦è¿°
è¿ç¨ï¼ç¨åºæ¯éæ¢çï¼è¿ç¨å®ä½çè¿è¡è¿ç¨å°±æ¯è¿ç¨ï¼æ¯ç³»ç»è¿è¡**èµæºåé
çåºæ¬åä½**
è¿ç¨çç¹å¾ï¼å¹¶åæ§ã弿¥æ§ã卿æ§ãç¬ç«æ§ãç»ææ§
**线ç¨**ï¼çº¿ç¨æ¯å±äºè¿ç¨çï¼æ¯ä¸ä¸ªåºæ¬ç CPU æ§è¡åå
ï¼æ¯ç¨åºæ§è¡æµçæå°åå
ãçº¿ç¨æ¯è¿ç¨ä¸çä¸ä¸ªå®ä½ï¼æ¯ç³»ç»**ç¬ç«è°åº¦çåºæ¬åä½**ï¼çº¿ç¨æ¬èº«ä¸æ¥æç³»ç»èµæºï¼åªæ¥æä¸ç¹å¨è¿è¡ä¸å¿
ä¸å¯å°çèµæºï¼ä¸åå±ä¸ä¸ªè¿ç¨çå
¶ä»çº¿ç¨å
±äº«è¿ç¨ææ¥æçå
¨é¨èµæº
å
³ç³»ï¼ä¸ä¸ªè¿ç¨å¯ä»¥å
å«å¤ä¸ªçº¿ç¨ï¼è¿å°±æ¯å¤çº¿ç¨ï¼æ¯å¦çè§é¢æ¯è¿ç¨ï¼å¾ç»ã声é³ã广åçå°±æ¯å¤ä¸ªçº¿ç¨
线ç¨çä½ç¨ï¼ä½¿å¤éç¨åºæ´å¥½çå¹¶åæ§è¡ï¼æé«èµæºå©ç¨çåç³»ç»ååéï¼å¢å¼ºæä½ç³»ç»çå¹¶åæ§è½
å¹¶åå¹¶è¡ï¼
* å¹¶è¡ï¼å¨å䏿¶å»ï¼æå¤ä¸ªæä»¤å¨å¤ä¸ª CPU ä¸åæ¶æ§è¡
* å¹¶åï¼å¨å䏿¶å»ï¼æå¤ä¸ªæä»¤å¨å个 CPU ä¸äº¤æ¿æ§è¡
忥弿¥ï¼
* éè¦çå¾
ç»æè¿åï¼æè½ç»§ç»è¿è¡å°±æ¯åæ¥
* ä¸éè¦çå¾
ç»æè¿åï¼å°±è½ç»§ç»è¿è¡å°±æ¯å¼æ¥
åèè§é¢ï¼https://www.bilibili.com/video/BV16J411h7Rd
ç¬è®°çæ´ä½ç»æä¾æ®è§é¢ç¼åï¼å¹¶éçå¦ä¹ çæ·±å
¥è¡¥å
äºå¾å¤ç¥è¯
***
### 对æ¯
线ç¨è¿ç¨å¯¹æ¯ï¼
* è¿ç¨åºæ¬ä¸ç¸äºç¬ç«çï¼è线ç¨åå¨äºè¿ç¨å
ï¼æ¯è¿ç¨çä¸ä¸ªåé
* è¿ç¨æ¥æå
±äº«çèµæºï¼å¦å
å空é´çï¼ä¾å
¶**å
é¨ç线ç¨å
񄧮**
* è¿ç¨é´éä¿¡è¾ä¸ºå¤æ
åä¸å°è®¡ç®æºçè¿ç¨é信称为 IPCï¼Inter-process communicationï¼
* ä¿¡å·éï¼ä¿¡å·éæ¯ä¸ä¸ªè®¡æ°å¨ï¼ç¨äºå¤è¿ç¨å¯¹å
±äº«æ°æ®ç访é®ï¼è§£å³åæ¥ç¸å
³çé®é¢å¹¶é¿å
ç«äºæ¡ä»¶
* å
±äº«åå¨ï¼å¤ä¸ªè¿ç¨å¯ä»¥è®¿é®åä¸åå
å空é´ï¼éè¦ä½¿ç¨ä¿¡å·éç¨æ¥åæ¥å¯¹å
±äº«åå¨ç访é®
* 管ééä¿¡ï¼ç®¡éæ¯ç¨äºè¿æ¥ä¸ä¸ªè¯»è¿ç¨åä¸ä¸ªåè¿ç¨ä»¥å®ç°å®ä»¬ä¹é´éä¿¡çä¸ä¸ªå
±äº«æä»¶ pipe æä»¶ï¼è¯¥æä»¶å䏿¶é´åªå
许ä¸ä¸ªè¿ç¨è®¿é®ï¼æä»¥åªæ¯æ**ååå·¥éä¿¡**
* å¿å管éï¼Pipesï¼ï¼ç¨äºå
·æäº²ç¼å
³ç³»çç¶åè¿ç¨é´æè
å
å¼è¿ç¨ä¹é´çéä¿¡
* å½å管éï¼Names Pipesï¼ï¼ä»¥ç£çæä»¶çæ¹å¼åå¨ï¼å¯ä»¥å®ç°æ¬æºä»»æä¸¤ä¸ªè¿ç¨éä¿¡ï¼éµå¾ª FIFO
* æ¶æ¯éåï¼å
æ ¸ä¸å卿¶æ¯çé¾è¡¨ï¼ç±æ¶æ¯éåæ è¯ç¬¦æ è¯ï¼è½å¨ä¸åè¿ç¨ä¹é´æä¾**å
¨åå·¥éä¿¡**ï¼å¯¹æ¯ç®¡éï¼
* å¿å管éåå¨äºå
åä¸çæä»¶ï¼å½å管éåå¨äºå®é
çç£çä»è´¨æè
æä»¶ç³»ç»ï¼æ¶æ¯éååæ¾å¨å
æ ¸ä¸ï¼åªæå¨å
æ ¸éå¯ï¼æä½ç³»ç»éå¯ï¼æè
æ¾ç¤ºå°å é¤ä¸ä¸ªæ¶æ¯éåæ¶ï¼è¯¥æ¶æ¯éåæè¢«çæ£å é¤
* 读è¿ç¨å¯ä»¥æ ¹æ®æ¶æ¯ç±»åæéæ©å°æ¥æ¶æ¶æ¯ï¼èä¸å FIFO 飿 ·åªè½é»è®¤å°æ¥æ¶
ä¸åè®¡ç®æºä¹é´ç**è¿ç¨éä¿¡**ï¼éè¦éè¿ç½ç»ï¼å¹¶éµå®å
±åçåè®®ï¼ä¾å¦ HTTP
* 奿¥åï¼ä¸å
¶å®éä¿¡æºå¶ä¸åçæ¯ï¼å¯ç¨äºä¸åæºå¨é´çäºç¸éä¿¡
* 线ç¨éä¿¡ç¸å¯¹ç®åï¼å 为线ç¨ä¹é´å
±äº«è¿ç¨å
çå
åï¼ä¸ä¸ªä¾åæ¯å¤ä¸ªçº¿ç¨å¯ä»¥è®¿é®åä¸ä¸ªå
±äº«åé
**Java ä¸çéä¿¡æºå¶**ï¼volatileãçå¾
/éç¥æºå¶ãjoin æ¹å¼ãInheritableThreadLocalãMappedByteBuffer
* çº¿ç¨æ´è½»éï¼çº¿ç¨ä¸ä¸æåæ¢ææ¬ä¸è¬ä¸è¦æ¯è¿ç¨ä¸ä¸æåæ¢ä½
***
## 线ç¨
### å建线ç¨
#### Thread
Thread åå»ºçº¿ç¨æ¹å¼ï¼å建线ç¨ç±»ï¼å¿åå
é¨ç±»æ¹å¼
* **start() æ¹æ³åºå±å
¶å®æ¯ç» CPU 注åå½å线ç¨ï¼å¹¶ä¸è§¦å run() æ¹æ³æ§è¡**
* 线ç¨çå¯å¨å¿
é¡»è°ç¨ start() æ¹æ³ï¼å¦æçº¿ç¨ç´æ¥è°ç¨ run() æ¹æ³ï¼ç¸å½äºåæäºæ®éç±»çæ§è¡ï¼æ¤æ¶ä¸»çº¿ç¨å°åªææ§è¡è¯¥çº¿ç¨
* 建议线ç¨å
å建å线ç¨ï¼ä¸»çº¿ç¨ç任塿¾å¨ä¹åï¼å¦å主线ç¨ï¼mainï¼æ°¸è¿æ¯å
æ§è¡å®
Thread æé å¨ï¼
* `public Thread()`
* `public Thread(String name)`
```java
public class ThreadDemo {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
for(int i = 0 ; i < 100 ; i++ ){
System.out.println("main线ç¨" + i)
}
// main线ç¨è¾åºæ¾å¨ä¸é¢ 就忿å
å顺åºäºï¼å ä¸ºæ¯ main 线ç¨é©±å¨çå线ç¨è¿è¡
}
}
class MyThread extends Thread {
@Override
public void run() {
for(int i = 0 ; i < 100 ; i++ ) {
System.out.println("å线ç¨è¾åºï¼"+i)
}
}
}
```
ç»§æ¿ Thread ç±»çä¼ç¼ºç¹ï¼
* ä¼ç¹ï¼ç¼ç ç®å
* 缺ç¹ï¼çº¿ç¨ç±»å·²ç»ç»§æ¿äº Thread ç±»æ æ³ç»§æ¿å
¶ä»ç±»äºï¼åè½ä¸è½éè¿ç»§æ¿æå±ï¼åç»§æ¿çå±éæ§ï¼
***
#### Runnable
Runnable åå»ºçº¿ç¨æ¹å¼ï¼å建线ç¨ç±»ï¼å¿åå
é¨ç±»æ¹å¼
Thread çæé å¨ï¼
* `public Thread(Runnable target)`
* `public Thread(Runnable target, String name)`
```java
public class ThreadDemo {
public static void main(String[] args) {
Runnable target = new MyRunnable();
Thread t1 = new Thread(target,"1å·çº¿ç¨");
t1.start();
Thread t2 = new Thread(target);//Thread-0
}
}
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i = 0 ; i < 10 ; i++ ){
System.out.println(Thread.currentThread().getName() + "->" + i);
}
}
}
```
**Thread ç±»æ¬èº«ä¹æ¯å®ç°äº Runnable æ¥å£**ï¼Thread ç±»ä¸ææ Runnable ç屿§ï¼æ§è¡çº¿ç¨ run æ¹æ³åºå±æ¯è°ç¨ Runnable#runï¼
```java
public class Thread implements Runnable {
private Runnable target;
public void run() {
if (target != null) {
// åºå±è°ç¨çæ¯ Runnable ç run æ¹æ³
target.run();
}
}
}
```
Runnable æ¹å¼çä¼ç¼ºç¹ï¼
* 缺ç¹ï¼ä»£ç 夿ä¸ç¹ã
* ä¼ç¹ï¼
1. 线ç¨ä»»å¡ç±»åªæ¯å®ç°äº Runnable æ¥å£ï¼å¯ä»¥ç»§ç»ç»§æ¿å
¶ä»ç±»ï¼é¿å
äºåç»§æ¿çå±éæ§
2. åä¸ä¸ªçº¿ç¨ä»»å¡å¯¹è±¡å¯ä»¥è¢«å
è£
æå¤ä¸ªçº¿ç¨å¯¹è±¡
3. éåå¤ä¸ªå¤ä¸ªçº¿ç¨å»å
±äº«åä¸ä¸ªèµæº
4. å®ç°è§£è¦æä½ï¼çº¿ç¨ä»»å¡ä»£ç å¯ä»¥è¢«å¤ä¸ªçº¿ç¨å
±äº«ï¼çº¿ç¨ä»»å¡ä»£ç å线ç¨ç¬ç«
5. çº¿ç¨æ± å¯ä»¥æ¾å
¥å®ç° Runnable æ Callable 线ç¨ä»»å¡å¯¹è±¡
â
****
#### Callable
å®ç° Callable æ¥å£ï¼
1. å®ä¹ä¸ä¸ªçº¿ç¨ä»»å¡ç±»å®ç° Callable æ¥å£ï¼ç³æçº¿ç¨æ§è¡çç»æç±»å
2. éå线ç¨ä»»å¡ç±»ç call æ¹æ³ï¼è¿ä¸ªæ¹æ³å¯ä»¥ç´æ¥è¿åæ§è¡çç»æ
3. å建ä¸ä¸ª Callable ç线ç¨ä»»å¡å¯¹è±¡
4. æ Callable ç线ç¨ä»»å¡å¯¹è±¡**å
è£
æä¸ä¸ªæªæ¥ä»»å¡å¯¹è±¡**
5. ææªæ¥ä»»å¡å¯¹è±¡å
è£
æçº¿ç¨å¯¹è±¡
6. è°ç¨çº¿ç¨ç start() æ¹æ³å¯å¨çº¿ç¨
`public FutureTask(Callable callable)`ï¼æªæ¥ä»»å¡å¯¹è±¡ï¼å¨çº¿ç¨æ§è¡å®åå¾å°çº¿ç¨çæ§è¡ç»æ
* FutureTask å°±æ¯ Runnable 对象ï¼å 为 **Thread ç±»åªè½æ§è¡ Runnable å®ä¾çä»»å¡å¯¹è±¡**ï¼æä»¥æ Callable å
è£
ææªæ¥ä»»å¡å¯¹è±¡
* çº¿ç¨æ± é¨åè¯¦è§£äº FutureTask çæºç
`public V get()`ï¼åæ¥çå¾
task æ§è¡å®æ¯çç»æï¼å¦æå¨çº¿ç¨ä¸è·åå¦ä¸ä¸ªçº¿ç¨æ§è¡ç»æï¼ä¼é»å¡çå¾
ï¼ç¨äºçº¿ç¨åæ¥
* get() 线ç¨ä¼é»å¡çå¾
任塿§è¡å®æ
* run() æ§è¡å®åä¼æç»æè®¾ç½®å° FutureTask çä¸ä¸ªæååéï¼get() 线ç¨å¯ä»¥è·åå°è¯¥åéçå¼
ä¼ç¼ºç¹ï¼
* ä¼ç¹ï¼å Runnableï¼å¹¶ä¸è½å¾å°çº¿ç¨æ§è¡çç»æ
* 缺ç¹ï¼ç¼ç 夿
```java
public class ThreadDemo {
public static void main(String[] args) {
Callable call = new MyCallable();
FutureTask task = new FutureTask<>(call);
Thread t = new Thread(task);
t.start();
try {
String s = task.get(); // è·åcallæ¹æ³è¿åçç»æï¼æ£å¸¸/å¼å¸¸ç»æï¼
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyCallable implements Callable {
@Override//éå线ç¨ä»»å¡ç±»æ¹æ³
public String call() throws Exception {
return Thread.currentThread().getName() + "->" + "Hello World";
}
}
```
***
### çº¿ç¨æ¹æ³
#### API
Thread ç±» APIï¼
| æ¹æ³ | 说æ |
| ------------------------------------------- | ------------------------------------------------------------ |
| public void start() | å¯å¨ä¸ä¸ªæ°çº¿ç¨ï¼Javaèææºè°ç¨æ¤çº¿ç¨ç run æ¹æ³ |
| public void run() | 线ç¨å¯å¨åè°ç¨è¯¥æ¹æ³ |
| public void setName(String name) | ç»å½å线ç¨ååå |
| public void getName() | è·åå½å线ç¨çåå
线ç¨åå¨é»è®¤åç§°ï¼åçº¿ç¨æ¯ Thread-ç´¢å¼ï¼ä¸»çº¿ç¨æ¯ main |
| public static Thread currentThread() | è·åå½å线ç¨å¯¹è±¡ï¼ä»£ç å¨åªä¸ªçº¿ç¨ä¸æ§è¡ |
| public static void sleep(long time) | 让å½å线ç¨ä¼ç å¤å°æ¯«ç§åç»§ç»æ§è¡
**Thread.sleep(0)** : 让æä½ç³»ç»ç«å»éæ°è¿è¡ä¸æ¬¡ CPU ç«äº |
| public static native void yield() | æç¤ºçº¿ç¨è°åº¦å¨è®©åºå½å线ç¨å¯¹ CPU çä½¿ç¨ |
| public final int getPriority() | è¿åæ¤çº¿ç¨çä¼å
级 |
| public final void setPriority(int priority) | æ´æ¹æ¤çº¿ç¨çä¼å
级ï¼å¸¸ç¨ 1 5 10 |
| public void interrupt() | 䏿è¿ä¸ªçº¿ç¨ï¼å¼å¸¸å¤çæºå¶ |
| public static boolean interrupted() | 夿å½åçº¿ç¨æ¯å¦è¢«ææï¼æ¸
é¤æææ è®° |
| public boolean isInterrupted() | 夿å½åçº¿ç¨æ¯å¦è¢«ææï¼ä¸æ¸
é¤æææ è®° |
| public final void join() | çå¾
è¿ä¸ªçº¿ç¨ç»æ |
| public final void join(long millis) | çå¾
è¿ä¸ªçº¿ç¨æ»äº¡ millis 毫ç§ï¼0 æå³çæ°¸è¿çå¾
|
| public final native boolean isAlive() | çº¿ç¨æ¯å¦åæ´»ï¼è¿æ²¡æè¿è¡å®æ¯ï¼ |
| public final void setDaemon(boolean on) | å°æ¤çº¿ç¨æ è®°ä¸ºå®æ¤çº¿ç¨æç¨æ·çº¿ç¨ |
***
#### run start
runï¼ç§°ä¸ºçº¿ç¨ä½ï¼å
å«äºè¦æ§è¡çè¿ä¸ªçº¿ç¨çå
å®¹ï¼æ¹æ³è¿è¡ç»æï¼æ¤çº¿ç¨éå³ç»æ¢ãç´æ¥è°ç¨ run æ¯å¨ä¸»çº¿ç¨ä¸æ§è¡äº runï¼æ²¡æå¯å¨æ°ç线ç¨ï¼éè¦é¡ºåºæ§è¡
startï¼ä½¿ç¨ start æ¯å¯å¨æ°ç线ç¨ï¼æ¤çº¿ç¨å¤äºå°±ç»ªï¼å¯è¿è¡ï¼ç¶æï¼éè¿æ°ç线ç¨é´æ¥æ§è¡ run ä¸ç代ç
说æï¼**çº¿ç¨æ§å¶èµæºç±»**
run() æ¹æ³ä¸çå¼å¸¸ä¸è½æåºï¼åªè½ try/catch
* å 为ç¶ç±»ä¸æ²¡ææåºä»»ä½å¼å¸¸ï¼åç±»ä¸è½æ¯ç¶ç±»æåºæ´å¤çå¼å¸¸
* **å¼å¸¸ä¸è½è·¨çº¿ç¨ä¼ æå main() ä¸**ï¼å æ¤å¿
须卿¬å°è¿è¡å¤ç
***
#### sleep yield
sleepï¼
* è°ç¨ sleep ä¼è®©å½å线ç¨ä» `Running` è¿å
¥ `Timed Waiting` ç¶æï¼é»å¡ï¼
* sleep() æ¹æ³çè¿ç¨ä¸ï¼**线ç¨ä¸ä¼éæ¾å¯¹è±¡é**
* å
¶å®çº¿ç¨å¯ä»¥ä½¿ç¨ interrupt æ¹æ³æææ£å¨ç¡ç ç线ç¨ï¼è¿æ¶ sleep æ¹æ³ä¼æåº InterruptedException
* ç¡ç ç»æåççº¿ç¨æªå¿
ä¼ç«å»å¾å°æ§è¡ï¼éè¦æ¢å CPU
* å»ºè®®ç¨ TimeUnit ç sleep ä»£æ¿ Thread ç sleep æ¥è·å¾æ´å¥½çå¯è¯»æ§
yieldï¼
* è°ç¨ yield ä¼è®©æç¤ºçº¿ç¨è°åº¦å¨è®©åºå½å线ç¨å¯¹ CPU ç使ç¨
* å
·ä½çå®ç°ä¾èµäºæä½ç³»ç»çä»»å¡è°åº¦å¨
* **伿¾å¼ CPU èµæºï¼éèµæºä¸ä¼éæ¾**
***
#### join
public final void join()ï¼çå¾
è¿ä¸ªçº¿ç¨ç»æ
åçï¼è°ç¨è
è½®è¯¢æ£æ¥çº¿ç¨ alive ç¶æï¼t1.join() çä»·äºï¼
```java
public final synchronized void join(long millis) throws InterruptedException {
// è°ç¨è
线ç¨è¿å
¥ thread ç waitSet çå¾
, ç´å°å½å线ç¨è¿è¡ç»æ
while (isAlive()) {
wait(0);
}
}
```
* join æ¹æ³æ¯è¢« synchronized 修饰çï¼æ¬è´¨ä¸æ¯ä¸ä¸ªå¯¹è±¡éï¼å
¶å
é¨ç wait æ¹æ³è°ç¨ä¹æ¯éæ¾éçï¼ä½æ¯**éæ¾çæ¯å½åç线ç¨å¯¹è±¡éï¼è䏿¯å¤é¢çé**
* å½è°ç¨æä¸ªçº¿ç¨ï¼t1ï¼ç join æ¹æ³åï¼è¯¥çº¿ç¨ï¼t1ï¼æ¢å å° CPU èµæºï¼å°±ä¸åéæ¾ï¼ç´å°çº¿ç¨æ§è¡å®æ¯
线ç¨åæ¥ï¼
* join å®ç°çº¿ç¨åæ¥ï¼å 为ä¼é»å¡çå¾
å¦ä¸ä¸ªçº¿ç¨çç»æï¼æè½ç»§ç»åä¸è¿è¡
* éè¦å¤é¨å
±äº«åéï¼ä¸ç¬¦åé¢å对象å°è£
çææ³
* å¿
é¡»çå¾
线ç¨ç»æï¼ä¸è½é
åçº¿ç¨æ± 使ç¨
* Future å®ç°ï¼åæ¥ï¼ï¼get() æ¹æ³é»å¡çå¾
æ§è¡ç»æ
* main çº¿ç¨æ¥æ¶ç»æ
* get æ¹æ³æ¯è®©è°ç¨çº¿ç¨åæ¥çå¾
```java
public class Test {
static int r = 0;
public static void main(String[] args) throws InterruptedException {
test1();
}
private static void test1() throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
r = 10;
});
t1.start();
t1.join();//ä¸çå¾
çº¿ç¨æ§è¡ç»æï¼è¾åºç10
System.out.println(r);
}
}
```
***
#### interrupt
##### ææçº¿ç¨
`public void interrupt()`ï¼ææè¿ä¸ªçº¿ç¨ï¼å¼å¸¸å¤çæºå¶
`public static boolean interrupted()`ï¼å¤æå½åçº¿ç¨æ¯å¦è¢«ææï¼ææè¿å trueï¼**æ¸
é¤æææ è®°**ï¼è¿ç»è°ç¨ä¸¤æ¬¡ä¸å®è¿å false
`public boolean isInterrupted()`ï¼å¤æå½åçº¿ç¨æ¯å¦è¢«ææï¼ä¸æ¸
é¤æææ è®°
ææç线ç¨ä¼åçä¸ä¸æåæ¢ï¼æä½ç³»ç»ä¼ä¿å线ç¨ä¿¡æ¯ï¼æ¢å å° CPU åä¼ä»ä¸æçå°æ¹æ¥çè¿è¡ï¼ææä¸æ¯åæ¢ï¼
* sleepãwaitãjoin æ¹æ³é½ä¼è®©çº¿ç¨è¿å
¥é»å¡ç¶æï¼ææçº¿ç¨**伿¸
空ææç¶æ**ï¼falseï¼
```java
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1");
t1.start();
Thread.sleep(500);
t1.interrupt();
System.out.println(" ææç¶æ: {}" + t1.isInterrupted());// ææç¶æ: {}false
}
```
* æææ£å¸¸è¿è¡ç线ç¨ï¼ä¸ä¼æ¸
空ææç¶æï¼trueï¼
```java
public static void main(String[] args) throws Exception {
Thread t2 = new Thread(()->{
while(true) {
Thread current = Thread.currentThread();
boolean interrupted = current.isInterrupted();
if(interrupted) {
System.out.println(" ææç¶æ: {}" + interrupted);//ææç¶æ: {}true
break;
}
}
}, "t2");
t2.start();
Thread.sleep(500);
t2.interrupt();
}
```
***
##### ææ park
park ä½ç¨ç±»ä¼¼ sleepï¼ææ park 线ç¨ï¼ä¸ä¼æ¸
空ææç¶æï¼trueï¼
```java
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println("park...");
LockSupport.park();
System.out.println("unpark...");
System.out.println("ææç¶æï¼" + Thread.currentThread().isInterrupted());//ææç¶æï¼true
}, "t1");
t1.start();
Thread.sleep(2000);
t1.interrupt();
}
```
å¦ææææ è®°å·²ç»æ¯ true, å park ä¼å¤±æ
```java
LockSupport.park();
System.out.println("unpark...");
LockSupport.park();//失æï¼ä¸ä¼é»å¡
System.out.println("unpark...");//åä¸ä¸ä¸ªunparkåæ¶æ§è¡
```
å¯ä»¥ä¿®æ¹è·åææç¶ææ¹æ³ï¼ä½¿ç¨ `Thread.interrupted()`ï¼æ¸
é¤æææ è®°
LockSupport ç±»å¨ åæ¥ â park-un 详解
***
##### ç»æ¢æ¨¡å¼
ç»æ¢æ¨¡å¼ä¹ä¸¤é¶æ®µç»æ¢æ¨¡å¼ï¼Two Phase Termination
ç®æ ï¼å¨ä¸ä¸ªçº¿ç¨ T1 ä¸å¦ä½ä¼é
ç»æ¢çº¿ç¨ T2ï¼ä¼é
æçæ¯ç» T2 ä¸ä¸ªåç½®å¤çå¨
éè¯¯ææ³ï¼
* 使ç¨çº¿ç¨å¯¹è±¡ç stop() æ¹æ³åæ¢çº¿ç¨ï¼stop æ¹æ³ä¼çæ£ææ»çº¿ç¨ï¼å¦æè¿æ¶çº¿ç¨éä½äºå
±äº«èµæºï¼å½å®è¢«ææ»åå°±å乿²¡ææºä¼éæ¾éï¼å
¶å®çº¿ç¨å°æ°¸è¿æ æ³è·åé
* ä½¿ç¨ System.exit(int) æ¹æ³åæ¢çº¿ç¨ï¼ç®çä»
æ¯åæ¢ä¸ä¸ªçº¿ç¨ï¼ä½è¿ç§åæ³ä¼è®©æ´ä¸ªç¨åºé½åæ¢
䏤鶿®µç»æ¢æ¨¡å¼å¾ç¤ºï¼
ææçº¿ç¨å¯è½å¨ä»»ä½æ¶é´ï¼æä»¥éè¦èèå¨ä»»ä½æ¶å»è¢«ææçå¤çæ¹æ³ï¼
```java
public class Test {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination tpt = new TwoPhaseTermination();
tpt.start();
Thread.sleep(3500);
tpt.stop();
}
}
class TwoPhaseTermination {
private Thread monitor;
// å¯å¨çæ§çº¿ç¨
public void start() {
monitor = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
Thread thread = Thread.currentThread();
if (thread.isInterrupted()) {
System.out.println("åç½®å¤ç");
break;
}
try {
Thread.sleep(1000); // ç¡ç
System.out.println("æ§è¡çæ§è®°å½"); // 卿¤è¢«ææä¸ä¼å¼å¸¸
} catch (InterruptedException e) { // å¨ç¡ç æé´è¢«ææï¼è¿å
¥å¼å¸¸å¤ççé»è¾
e.printStackTrace();
// éæ°è®¾ç½®æææ è®°ï¼ææ sleep 伿¸
餿æç¶æ
thread.interrupt();
}
}
}
});
monitor.start();
}
// åæ¢çæ§çº¿ç¨
public void stop() {
monitor.interrupt();
}
}
```
***
#### daemon
`public final void setDaemon(boolean on)`ï¼å¦ææ¯ true ï¼å°æ¤çº¿ç¨æ è®°ä¸ºå®æ¤çº¿ç¨
线ç¨**å¯å¨å**è°ç¨æ¤æ¹æ³ï¼
```java
Thread t = new Thread() {
@Override
public void run() {
System.out.println("running");
}
};
// 设置该线ç¨ä¸ºå®æ¤çº¿ç¨
t.setDaemon(true);
t.start();
```
ç¨æ·çº¿ç¨ï¼å¹³å¸¸åå»ºçæ®é线ç¨
宿¤çº¿ç¨ï¼æå¡äºç¨æ·çº¿ç¨ï¼åªè¦å
¶å®é宿¤çº¿ç¨è¿è¡ç»æäºï¼å³ä½¿å®æ¤çº¿ç¨ä»£ç æ²¡ææ§è¡å®ï¼ä¹ä¼å¼ºå¶ç»æã宿¤è¿ç¨æ¯**è±ç¦»äºç»ç«¯å¹¶ä¸å¨åå°è¿è¡çè¿ç¨**ï¼è±ç¦»ç»ç«¯æ¯ä¸ºäºé¿å
卿§è¡çè¿ç¨ä¸çä¿¡æ¯å¨ç»ç«¯ä¸æ¾ç¤º
说æï¼å½è¿è¡ç线ç¨é½æ¯å®æ¤çº¿ç¨ï¼Java èææºå°éåºï¼å 为æ®éçº¿ç¨æ§è¡å®åï¼JVM æ¯å®æ¤çº¿ç¨ï¼ä¸ä¼ç»§ç»è¿è¡ä¸å»
常è§ç宿¤çº¿ç¨ï¼
* åå¾åæ¶å¨çº¿ç¨å°±æ¯ä¸ç§å®æ¤çº¿ç¨
* Tomcat ä¸ç Acceptor å Poller 线ç¨é½æ¯å®æ¤çº¿ç¨ï¼æä»¥ Tomcat æ¥æ¶å° shutdown å½ä»¤åï¼ä¸ä¼çå¾
å®ä»¬å¤çå®å½å请æ±
***
#### 䏿¨è
䏿¨è使ç¨çæ¹æ³ï¼è¿äºæ¹æ³å·²è¿æ¶ï¼å®¹æç ´å忥代ç åï¼é æçº¿ç¨æ»éï¼
* `public final void stop()`ï¼åæ¢çº¿ç¨è¿è¡
åºå¼åå ï¼æ¹æ³ç²æ´ï¼é¤éå¯è½æ§è¡ finally 代ç å以åéæ¾ synchronized å¤ï¼çº¿ç¨å°ç´æ¥è¢«ç»æ¢ï¼å¦æçº¿ç¨ææ JUC çäºæ¥éå¯è½å¯¼è´éæ¥ä¸åéæ¾ï¼é æå
¶ä»çº¿ç¨æ°¸è¿çå¾
çå±é¢
* `public final void suspend()`ï¼**æèµ·ï¼æåï¼çº¿ç¨è¿è¡**
åºå¼åå ï¼å¦æç®æ 线ç¨å¨æåæ¶å¯¹ç³»ç»èµæºææéï¼åå¨ç®æ çº¿ç¨æ¢å¤ä¹å没æçº¿ç¨å¯ä»¥è®¿é®è¯¥èµæºï¼å¦æ**æ¢å¤ç®æ 线ç¨ç线ç¨**å¨è°ç¨ resume ä¹åä¼å°è¯è®¿é®æ¤å
±äº«èµæºï¼åä¼å¯¼è´æ»é
* `public final void resume()`ï¼æ¢å¤çº¿ç¨è¿è¡
***
### 线ç¨åç
#### è¿è¡æºå¶
Java Virtual Machine Stacksï¼Java èææºæ ï¼ï¼æ¯ä¸ªçº¿ç¨å¯å¨åï¼èææºå°±ä¼ä¸ºå
¶åé
ä¸åæ å
å
* æ¯ä¸ªæ ç±å¤ä¸ªæ 帧ï¼Frameï¼ç»æï¼å¯¹åºçæ¯æ¬¡æ¹æ³è°ç¨æ¶æå ç¨çå
å
* æ¯ä¸ªçº¿ç¨åªè½æä¸ä¸ªæ´»å¨æ 帧ï¼å¯¹åºçå½åæ£å¨æ§è¡çé£ä¸ªæ¹æ³
线ç¨ä¸ä¸æåæ¢ï¼Thread Context Switchï¼ï¼ä¸äºåå å¯¼è´ CPU ä¸åæ§è¡å½å线ç¨ï¼è½¬èæ§è¡å¦ä¸ä¸ªçº¿ç¨
* 线ç¨ç CPU æ¶é´çç¨å®
* åå¾åæ¶
* ææ´é«ä¼å
级ç线ç¨éè¦è¿è¡
* 线ç¨èªå·±è°ç¨äº sleepãyieldãwaitãjoinãpark çæ¹æ³
ç¨åºè®¡æ°å¨ï¼Program Counter Registerï¼ï¼è®°ä½ä¸ä¸æ¡ JVM æä»¤çæ§è¡å°åï¼æ¯çº¿ç¨ç§æç
å½ Context Switch åçæ¶ï¼éè¦ç±æä½ç³»ç»ä¿åå½å线ç¨çç¶æï¼PCB ä¸ï¼ï¼å¹¶æ¢å¤å¦ä¸ä¸ªçº¿ç¨çç¶æï¼å
æ¬ç¨åºè®¡æ°å¨ãèææºæ 䏿¯ä¸ªæ 帧çä¿¡æ¯ï¼å¦å±é¨åéãæä½æ°æ ãè¿åå°åç
JVM è§è并没æéå®çº¿ç¨æ¨¡åï¼ä»¥ HotSopot 为ä¾ï¼
* Java ççº¿ç¨æ¯å
æ ¸çº§çº¿ç¨ï¼1:1 çº¿ç¨æ¨¡åï¼ï¼æ¯ä¸ª Java 线ç¨é½æ å°å°ä¸ä¸ªæä½ç³»ç»åç线ç¨ï¼éè¦æ¶èä¸å®çå
æ ¸èµæºï¼å æ ï¼
* **线ç¨çè°åº¦æ¯å¨å
æ ¸æè¿è¡çï¼è线ç¨ä¸çä»£ç æ¯å¨ç¨æ·æè¿è¡**ï¼æä»¥çº¿ç¨åæ¢ï¼ç¶ææ¹åï¼ä¼å¯¼è´ç¨æ·ä¸å
æ ¸æè½¬æ¢è¿è¡ç³»ç»è°ç¨ï¼è¿æ¯é常æ¶èæ§è½
Java ä¸ main æ¹æ³å¯å¨çæ¯ä¸ä¸ªè¿ç¨ä¹æ¯ä¸ä¸ªä¸»çº¿ç¨ï¼main æ¹æ³éé¢çå
¶ä»çº¿ç¨å为å线ç¨ï¼main çº¿ç¨æ¯è¿äºçº¿ç¨çç¶çº¿ç¨
***
#### 线ç¨è°åº¦
线ç¨è°åº¦æç³»ç»ä¸ºçº¿ç¨åé
å¤çå¨ä½¿ç¨æçè¿ç¨ï¼æ¹å¼æä¸¤ç§ï¼ååå¼çº¿ç¨è°åº¦ãæ¢å å¼çº¿ç¨è°åº¦ï¼Java éæ©ï¼
ååå¼çº¿ç¨è°åº¦ï¼çº¿ç¨çæ§è¡æ¶é´ç±çº¿ç¨æ¬èº«æ§å¶
* ä¼ç¹ï¼çº¿ç¨åå®ä»»å¡æéç¥ç³»ç»åæ¢å°å
¶ä»çº¿ç¨ï¼ç¸å½äºææçº¿ç¨ä¸²è¡æ§è¡ï¼ä¸ä¼åºç°çº¿ç¨åæ¥é®é¢
* 缺ç¹ï¼çº¿ç¨æ§è¡æ¶é´ä¸å¯æ§ï¼å¦æä»£ç ç¼ååºç°é®é¢ï¼å¯è½å¯¼è´ç¨åºä¸ç´é»å¡ï¼å¼èµ·ç³»ç»ç奿º
æ¢å å¼çº¿ç¨è°åº¦ï¼çº¿ç¨çæ§è¡æ¶é´ç±ç³»ç»åé
* ä¼ç¹ï¼çº¿ç¨æ§è¡æ¶é´å¯æ§ï¼ä¸ä¼å 为ä¸ä¸ªçº¿ç¨çé®é¢èå¯¼è´æ´ä½ç³»ç»ä¸å¯ç¨
* 缺ç¹ï¼æ æ³ä¸»å¨ä¸ºæä¸ªçº¿ç¨å¤åé
æ¶é´
Java æä¾äºçº¿ç¨ä¼å
çº§çæºå¶ï¼ä¼å
çº§ä¼æç¤ºï¼hintï¼è°åº¦å¨ä¼å
è°åº¦è¯¥çº¿ç¨ï¼ä½è¿ä»
ä»
æ¯ä¸ä¸ªæç¤ºï¼è°åº¦å¨å¯ä»¥å¿½ç¥å®ãå¨çº¿ç¨çå°±ç»ªç¶ææ¶ï¼å¦æ CPU æ¯è¾å¿ï¼é£ä¹ä¼å
级é«ç线ç¨ä¼è·å¾æ´å¤çæ¶é´çï¼ä½ CPU 鲿¶ï¼ä¼å
级å 乿²¡ä½ç¨
说æï¼å¹¶ä¸è½éè¿ä¼å
级æ¥å¤æçº¿ç¨æ§è¡çå
å顺åº
***
#### æªæ¥ä¼å
å
æ ¸çº§çº¿ç¨è°åº¦çææ¬è¾å¤§ï¼æä»¥å¼å
¥äºæ´è½»é级çåç¨ãç¨æ·çº¿ç¨çè°åº¦ç±ç¨æ·èªå·±å®ç°ï¼ä¸å¯¹å¤ççº¿ç¨æ¨¡åï¼ï¼è¢«è®¾è®¡ä¸ºååå¼è°åº¦ï¼æä»¥å«åç¨
* ææ åç¨ï¼åç¨ä¼å®æ´çåè°ç¨æ çä¿æ¤ãæ¢å¤å·¥ä½ï¼æä»¥å«ææ åç¨
* æ æ åç¨ï¼æ¬è´¨ä¸æ¯ä¸ç§æéç¶ææºï¼ç¶æä¿åå¨éå
éï¼æ¯ææ åç¨æ´è½»éï¼ä½æ¯åè½æé
ææ åç¨ä¸æä¸ç§ç¹ä¾å«çº¤ç¨ï¼å¨æ°å¹¶å模åä¸ï¼ä¸æ®µçº¤ç¨ç代ç 被å为两é¨åï¼æ§è¡è¿ç¨åè°åº¦å¨ï¼
* æ§è¡è¿ç¨ï¼ç¨äºç»´æ¤æ§è¡ç°åºï¼ä¿æ¤ãæ¢å¤ä¸ä¸æç¶æ
* è°åº¦å¨ï¼è´è´£ç¼æææè¦æ§è¡ç代ç 顺åº
****
### 线ç¨ç¶æ
è¿ç¨çç¶æåèæä½ç³»ç»ï¼å建æã就绪æãè¿è¡æãé»å¡æãç»æ¢æ
线ç¨ç±çå°æ»ç宿´è¿ç¨ï¼çå½å¨æï¼ï¼å½çº¿ç¨è¢«å建并å¯å¨ä»¥åï¼æ¢ä¸æ¯ä¸å¯å¨å°±è¿å
¥äºæ§è¡ç¶æï¼ä¹ä¸æ¯ä¸ç´å¤äºæ§è¡ç¶æï¼å¨ API ä¸ `java.lang.Thread.State` è¿ä¸ªæä¸¾ä¸ç»åºäºå
ç§çº¿ç¨ç¶æï¼
| 线ç¨ç¶æ | 导è´ç¶æåçæ¡ä»¶ |
| -------------------------- | ------------------------------------------------------------ |
| NEWï¼æ°å»ºï¼ | 线ç¨å被å建ï¼ä½æ¯å¹¶æªå¯å¨ï¼è¿æ²¡è°ç¨ start æ¹æ³ï¼åªæçº¿ç¨å¯¹è±¡ï¼æ²¡æçº¿ç¨ç¹å¾ |
| Runnableï¼å¯è¿è¡ï¼ | 线ç¨å¯ä»¥å¨ Java èææºä¸è¿è¡çç¶æï¼å¯è½æ£å¨è¿è¡èªå·±ä»£ç ï¼ä¹å¯è½æ²¡æï¼è¿åå³äºæä½ç³»ç»å¤çå¨ï¼è°ç¨äº t.start() æ¹æ³ï¼å°±ç»ªï¼ç»å
¸å«æ³ï¼ |
| Blockedï¼é»å¡ï¼ | å½ä¸ä¸ªçº¿ç¨è¯å¾è·åä¸ä¸ªå¯¹è±¡éï¼è该对象é被å
¶ä»ççº¿ç¨ææï¼å该线ç¨è¿å
¥ Blocked ç¶æï¼å½è¯¥çº¿ç¨ææéæ¶ï¼è¯¥çº¿ç¨å°åæ Runnable ç¶æ |
| Waitingï¼æ éçå¾
ï¼ | ä¸ä¸ªçº¿ç¨å¨çå¾
å¦ä¸ä¸ªçº¿ç¨æ§è¡ä¸ä¸ªï¼å¤éï¼å¨ä½æ¶ï¼è¯¥çº¿ç¨è¿å
¥ Waiting ç¶æï¼è¿å
¥è¿ä¸ªç¶æåä¸è½èªå¨å¤éï¼å¿
é¡»çå¾
å¦ä¸ä¸ªçº¿ç¨è°ç¨ notify æè
notifyAll æ¹æ³æè½å¤é |
| Timed Waiting ï¼éæçå¾
ï¼ | æå ä¸ªæ¹æ³æè¶
æ¶åæ°ï¼è°ç¨å°è¿å
¥ Timed Waiting ç¶æï¼è¿ä¸ç¶æå°ä¸ç´ä¿æå°è¶
æ¶ææ»¡æè
æ¥æ¶å°å¤ééç¥ã带æè¶
æ¶åæ°çå¸¸ç¨æ¹æ³æ Thread.sleep ãObject.wait |
| Teminatedï¼ç»æï¼ | run æ¹æ³æ£å¸¸éåºèæ»äº¡ï¼æè
å 为没ææè·çå¼å¸¸ç»æ¢äº run æ¹æ³èæ»äº¡ |

* NEW â RUNNABLEï¼å½è°ç¨ t.start() æ¹æ³æ¶ï¼ç± NEW â RUNNABLE
* RUNNABLE <--> WAITINGï¼
* è°ç¨ obj.wait() æ¹æ³æ¶
è°ç¨ obj.notify()ãobj.notifyAll()ãt.interrupt()ï¼
* ç«äºéæåï¼t 线ç¨ä» WAITING â RUNNABLE
* ç«äºé失败ï¼t 线ç¨ä» WAITING â BLOCKED
* å½å线ç¨è°ç¨ t.join() æ¹æ³ï¼æ³¨ææ¯å½å线ç¨å¨ t 线ç¨å¯¹è±¡ççè§å¨ä¸çå¾
* å½å线ç¨è°ç¨ LockSupport.park() æ¹æ³
* RUNNABLE <--> TIMED_WAITINGï¼è°ç¨ obj.wait(long n) æ¹æ³ãå½å线ç¨è°ç¨ t.join(long n) æ¹æ³ãå½å线ç¨è°ç¨ Thread.sleep(long n)
* RUNNABLE <--> BLOCKEDï¼t 线ç¨ç¨ synchronized(obj) è·åäºå¯¹è±¡éæ¶ç«äºå¤±è´¥
***
### æ¥ç线ç¨
Windowsï¼
* ä»»å¡ç®¡çå¨å¯ä»¥æ¥çè¿ç¨åçº¿ç¨æ°ï¼ä¹å¯ä»¥ç¨æ¥ææ»è¿ç¨
* tasklist æ¥çè¿ç¨
* taskkill ææ»è¿ç¨
Linuxï¼
* ps -ef æ¥çææè¿ç¨
* ps -fT -p æ¥çæä¸ªè¿ç¨ï¼PIDï¼çææçº¿ç¨
* kill ææ»è¿ç¨
* top æå¤§å H 忢æ¯å¦æ¾ç¤ºçº¿ç¨
* top -H -p æ¥çæä¸ªè¿ç¨ï¼PIDï¼çææçº¿ç¨
Javaï¼
* jps å½ä»¤æ¥çææ Java è¿ç¨
* jstack æ¥çæä¸ª Java è¿ç¨ï¼PIDï¼çææçº¿ç¨ç¶æ
* jconsole æ¥æ¥çæä¸ª Java è¿ç¨ä¸çº¿ç¨çè¿è¡æ
åµï¼å¾å½¢çé¢ï¼
***
## 忥
### 临çåº
临çèµæºï¼ä¸æ¬¡ä»
å
许ä¸ä¸ªè¿ç¨ä½¿ç¨çèµæºæä¸ºä¸´çèµæº
临çåºï¼è®¿é®ä¸´çèµæºç代ç å
ç«ææ¡ä»¶ï¼å¤ä¸ªçº¿ç¨å¨ä¸´çåºå
æ§è¡ï¼ç±äºä»£ç çæ§è¡åºåä¸åè导è´ç»ææ æ³é¢æµï¼ç§°ä¹ä¸ºåçäºç«ææ¡ä»¶
ä¸ä¸ªç¨åºè¿è¡å¤ä¸ªçº¿ç¨æ¯æ²¡æé®é¢ï¼å¤ä¸ªçº¿ç¨è¯»å
±äº«èµæºä¹æ²¡æé®é¢ï¼å¨å¤ä¸ªçº¿ç¨å¯¹å
±äº«èµæºè¯»åæä½æ¶åçæä»¤äº¤éï¼å°±ä¼åºç°é®é¢
为äºé¿å
临çåºçç«ææ¡ä»¶åçï¼è§£å³çº¿ç¨å®å
¨é®é¢ï¼ï¼
* é»å¡å¼çè§£å³æ¹æ¡ï¼synchronizedï¼lock
* éé»å¡å¼çè§£å³æ¹æ¡ï¼åååé
管ç¨ï¼monitorï¼ï¼ç±å±é¨äºèªå·±çè¥å¹²å
Œ
±åéåææè®¿é®è¿äºå
Œ
±åéçè¿ç¨æç»æç软件模åï¼ä¿è¯å䏿¶å»åªæä¸ä¸ªè¿ç¨å¨ç®¡ç¨å
æ´»å¨ï¼å³ç®¡ç¨å
å®ä¹çæä½å¨å䏿¶å»åªè¢«ä¸ä¸ªè¿ç¨è°ç¨ï¼ç±ç¼è¯å¨å®ç°ï¼
**synchronizedï¼å¯¹è±¡éï¼ä¿è¯äºä¸´çåºå
代ç çååæ§**ï¼éç¨äºæ¥çæ¹å¼è®©å䏿¶å»è³å¤åªæä¸ä¸ªçº¿ç¨è½ææå¯¹è±¡éï¼å
¶å®çº¿ç¨è·åè¿ä¸ªå¯¹è±¡éæ¶ä¼é»å¡ï¼ä¿è¯æ¥æéç线ç¨å¯ä»¥å®å
¨çæ§è¡ä¸´çåºå
ç代ç ï¼ä¸ç¨æ
å¿çº¿ç¨ä¸ä¸æåæ¢
äºæ¥å忥é½å¯ä»¥éç¨ synchronized å
³é®åæ¥å®æï¼åºå«ï¼
* äºæ¥æ¯ä¿è¯ä¸´çåºçç«ææ¡ä»¶åçï¼å䏿¶å»åªè½æä¸ä¸ªçº¿ç¨æ§è¡ä¸´çåºä»£ç
* 忥æ¯ç±äºçº¿ç¨æ§è¡çå
åã顺åºä¸åãéè¦ä¸ä¸ªçº¿ç¨çå¾
å
¶å®çº¿ç¨è¿è¡å°æä¸ªç¹
æ§è½ï¼
* 线ç¨å®å
¨ï¼æ§è½å·®
* 线ç¨ä¸å®å
¨æ§è½å¥½ï¼åå¦å¼åä¸ä¸ä¼åå¨å¤çº¿ç¨å®å
¨é®é¢ï¼å»ºè®®ä½¿ç¨çº¿ç¨ä¸å®å
¨ç设计类
***
### syn-ed
#### 使ç¨é
##### 忥å
é对象ï¼ç论ä¸å¯ä»¥æ¯**ä»»æçå¯ä¸å¯¹è±¡**
synchronized æ¯å¯éå
¥ãä¸å
¬å¹³çéé级é
ååä¸ï¼
* é对象建议使ç¨å
±äº«èµæº
* å¨å®ä¾æ¹æ³ä¸ä½¿ç¨ this ä½ä¸ºé对象ï¼éä½ç this æ£å¥½æ¯å
±äº«èµæº
* å¨éææ¹æ³ä¸ä½¿ç¨ç±»å .class åèç ä½ä¸ºé对象ï¼å ä¸ºéææåå±äºç±»ï¼è¢«ææå®ä¾å¯¹è±¡å
±äº«ï¼æä»¥éè¦éä½ç±»
忥代ç åæ ¼å¼ï¼
```java
synchronized(é对象){
// 访é®å
±äº«èµæºçæ ¸å¿ä»£ç
}
```
å®ä¾ï¼
```java
public class demo {
static int counter = 0;
//static修饰ï¼åå
ç´ æ¯å±äºç±»æ¬èº«çï¼ä¸å±äºå¯¹è±¡ ï¼ä¸ç±»ä¸èµ·å è½½ä¸æ¬¡ï¼åªæä¸ä¸ª
static final Object room = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
synchronized (room) {
counter++;
}
}
}, "t1");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
synchronized (room) {
counter--;
}
}
}, "t2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter);
}
}
```
***
##### åæ¥æ¹æ³
æåºç°çº¿ç¨å®å
¨é®é¢çæ ¸å¿æ¹æ³éèµ·æ¥ï¼æ¯æ¬¡åªè½ä¸ä¸ªçº¿ç¨è¿å
¥è®¿é®
synchronized ä¿®é¥°çæ¹æ³çä¸å
·å¤ç»§æ¿æ§ï¼æä»¥åç±»æ¯çº¿ç¨ä¸å®å
¨çï¼å¦æåç±»çæ¹æ³ä¹è¢« synchronized 修饰ï¼ä¸¤ä¸ªé对象å
¶å®æ¯ä¸æéï¼è䏿¯**å类对象ä½ä¸ºé**
ç¨æ³ï¼ç´æ¥ç»æ¹æ³å ä¸ä¸ä¸ªä¿®é¥°ç¬¦ synchronized
```java
//åæ¥æ¹æ³
修饰符 synchronized è¿åå¼ç±»å æ¹æ³å(æ¹æ³åæ°) {
æ¹æ³ä½ï¼
}
//忥鿿¹æ³
修饰符 static synchronized è¿åå¼ç±»å æ¹æ³å(æ¹æ³åæ°) {
æ¹æ³ä½ï¼
}
```
åæ¥æ¹æ³åºå±ä¹æ¯æé对象çï¼
* å¦ææ¹æ³æ¯å®ä¾æ¹æ³ï¼åæ¥æ¹æ³é»è®¤ç¨ this ä½ä¸ºçé对象
```java
public synchronized void test() {} //çä»·äº
public void test() {
synchronized(this) {}
}
```
* å¦ææ¹æ³æ¯éææ¹æ³ï¼åæ¥æ¹æ³é»è®¤ç¨ç±»å .class ä½ä¸ºçé对象
```java
class Test{
public synchronized static void test() {}
}
//çä»·äº
class Test{
public void test() {
synchronized(Test.class) {}
}
}
```
***
##### 线ç¨å
«é
线ç¨å
«éå°±æ¯èå¯ synchronized éä½çæ¯åªä¸ªå¯¹è±¡ï¼ç´æ¥ç¾åº¦æç´¢ç¸å
³çå®ä¾
说æï¼ä¸»è¦å
³æ³¨éä½ç对象æ¯ä¸æ¯åä¸ä¸ª
* éä½ç±»å¯¹è±¡ï¼ææç±»çå®ä¾çæ¹æ³é½æ¯å®å
¨çï¼ç±»çææå®ä¾é½ç¸å½äºå䏿é
* éä½ this 对象ï¼åªæå¨å½åå®ä¾å¯¹è±¡ç线ç¨å
æ¯å®å
¨çï¼å¦ææå¤ä¸ªå®ä¾å°±ä¸å®å
¨
线ç¨ä¸å®å
¨ï¼å 为éä½ç䏿¯åä¸ä¸ªå¯¹è±¡ï¼çº¿ç¨ 1 è°ç¨ a æ¹æ³éä½ç类对象ï¼çº¿ç¨ 2 è°ç¨ b æ¹æ³éä½ç n2 对象ï¼ä¸æ¯åä¸ä¸ªå¯¹è±¡
```java
class Number{
public static synchronized void a(){
Thread.sleep(1000);
System.out.println("1");
}
public synchronized void b() {
System.out.println("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
```
线ç¨å®å
¨ï¼å 为 n1 è°ç¨ a() æ¹æ³ï¼éä½çæ¯ç±»å¯¹è±¡ï¼n2 è°ç¨ b() æ¹æ³ï¼éä½ç乿¯ç±»å¯¹è±¡ï¼æä»¥çº¿ç¨å®å
¨
```java
class Number{
public static synchronized void a(){
Thread.sleep(1000);
System.out.println("1");
}
public static synchronized void b() {
System.out.println("2");
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
```
***
#### éåç
##### Monitor
Monitor 被翻è¯ä¸ºçè§å¨æç®¡ç¨
æ¯ä¸ª Java 对象é½å¯ä»¥å
³èä¸ä¸ª Monitor 对象ï¼Monitor 乿¯ classï¼å
¶**å®ä¾åå¨å¨å ä¸**ï¼å¦æä½¿ç¨ synchronized ç»å¯¹è±¡ä¸éï¼éé级ï¼ä¹åï¼è¯¥å¯¹è±¡å¤´ç Mark Word ä¸å°±è¢«è®¾ç½®æå Monitor 对象çæéï¼è¿å°±æ¯éé级é
* Mark Word ç»æï¼æå䏤使¯**éæ å¿ä½**

* 64 ä½èææº Mark Wordï¼

工使µç¨ï¼
* å¼å§æ¶ Monitor ä¸ Owner 为 null
* å½ Thread-2 æ§è¡ synchronized(obj) å°±ä¼å° Monitor çææè
Owner 置为 Thread-2ï¼Monitor ä¸åªè½æä¸ä¸ª Ownerï¼**obj 对象ç Mark Word æå Monitor**ï¼æ**对象åæç MarkWord åå
¥çº¿ç¨æ ä¸çéè®°å½**ä¸ï¼è½»é级éé¨å详解ï¼
* å¨ Thread-2 ä¸éçè¿ç¨ï¼Thread-3ãThread-4ãThread-5 乿§è¡ synchronized(obj)ï¼å°±ä¼è¿å
¥ EntryList BLOCKEDï¼ååé¾è¡¨ï¼
* Thread-2 æ§è¡å®åæ¥ä»£ç åçå
å®¹ï¼æ ¹æ® obj å¯¹è±¡å¤´ä¸ Monitor å°å寻æ¾ï¼è®¾ç½® Owner ä¸ºç©ºï¼æçº¿ç¨æ çéè®°å½ä¸ç对象头çå¼è®¾ç½®å MarkWord
* å¤é EntryList ä¸çå¾
ççº¿ç¨æ¥ç«äºéï¼ç«äºæ¯**éå
¬å¹³ç**ï¼å¦æè¿æ¶ææ°ççº¿ç¨æ³è¦è·åéï¼å¯è½ç´æ¥å°±æ¢å å°äºï¼é»å¡éåç线ç¨å°±ä¼ç»§ç»é»å¡
* WaitSet ä¸ç Thread-0ï¼æ¯ä»¥åè·å¾è¿éï¼ä½æ¡ä»¶ä¸æ»¡è¶³è¿å
¥ WAITING ç¶æç线ç¨ï¼wait-notify æºå¶ï¼

注æï¼
* synchronized å¿
é¡»æ¯è¿å
¥åä¸ä¸ªå¯¹è±¡ç Monitor ææä¸è¿°çææ
* ä¸å synchronized ç对象ä¸ä¼å
³èçè§å¨ï¼ä¸éµä»ä»¥ä¸è§å
****
##### åèç
代ç ï¼
```java
public static void main(String[] args) {
Object lock = new Object();
synchronized (lock) {
System.out.println("ok");
}
}
```
```java
0: new #2 // new Object
3: dup
4: invokespecial #1 // invokespecial :()Vï¼éèæ¹æ³
7: astore_1 // lockå¼ç¨ -> lock
8: aload_1 // lock ï¼synchronizedå¼å§ï¼
9: dup // ä¸ä»½ç¨æ¥åå§åï¼ä¸ä»½ç¨æ¥å¼ç¨
10: astore_2 // lockå¼ç¨ -> slot 2
11: monitorenter // ãå° lock对象 MarkWord 置为 Monitor æéã
12: getstatic #3 // System.out
15: ldc #4 // "ok"
17: invokevirtual #5 // invokevirtual println:(Ljava/lang/String;)V
20: aload_2 // slot 2(lockå¼ç¨)
21: monitorexit // ãå° lock对象 MarkWord éç½®, å¤é EntryListã
22: goto 30
25: astore_3 // any -> slot 3
26: aload_2 // slot 2(lockå¼ç¨)
27: monitorexit // ãå° lock对象 MarkWord éç½®, å¤é EntryListã
28: aload_3
29: athrow
30: return
Exception table:
from to target type
12 22 25 any
25 28 25 any
LineNumberTable: ...
LocalVariableTable:
Start Length Slot Name Signature
0 31 0 args [Ljava/lang/String;
8 23 1 lock Ljava/lang/Object;
```
说æï¼
* éè¿å¼å¸¸ **try-catch æºå¶**ï¼ç¡®ä¿ä¸å®ä¼è¢«è§£é
* æ¹æ³çº§å«ç synchronized ä¸ä¼å¨åèç æä»¤ä¸ææä½ç°
***
#### éå级
##### å级è¿ç¨
**synchronized æ¯å¯éå
¥ãä¸å
¬å¹³çéé级é**ï¼æä»¥å¯ä»¥å¯¹å
¶è¿è¡ä¼å
```java
æ é -> ååé -> è½»é级é -> éé级é // éçç«äºçå¢å ï¼åªè½éå级ï¼ä¸è½é级
```

***
##### ååé
ååéçææ³æ¯ååäºè®©ç¬¬ä¸ä¸ªè·åé对象ç线ç¨ï¼è¿ä¸ªçº¿ç¨ä¹åéæ°è·å该éä¸åéè¦åæ¥æä½ï¼
* å½éå¯¹è±¡ç¬¬ä¸æ¬¡è¢«çº¿ç¨è·å¾çæ¶åè¿å
¥ååç¶æï¼æ 记为 101ï¼åæ¶**ä½¿ç¨ CAS æä½å°çº¿ç¨ ID è®°å½å° Mark Word**ã妿 CAS æä½æåï¼è¿ä¸ªçº¿ç¨ä»¥åè¿å
¥è¿ä¸ªéç¸å
³ç忥åï¼æ¥çè¿ä¸ªçº¿ç¨ ID æ¯èªå·±ç就表示没æç«äºï¼å°±ä¸éè¦åè¿è¡ä»»ä½åæ¥æä½
* 彿å¦å¤ä¸ä¸ªçº¿ç¨å»å°è¯è·åè¿ä¸ªé对象æ¶ï¼ååç¶æå°±å®£åç»æï¼æ¤æ¶æ¤éååï¼Revoke Biasï¼åæ¢å¤å°æªéå®æè½»é级éç¶æ
ä¸ä¸ªå¯¹è±¡å建æ¶ï¼
* 妿å¼å¯äºååéï¼é»è®¤å¼å¯ï¼ï¼é£ä¹å¯¹è±¡å建åï¼MarkWord å¼ä¸º 0x05 峿å 3 ä½ä¸º 101ï¼threadãepochãage é½ä¸º 0
* åå鿝é»è®¤æ¯å»¶è¿çï¼ä¸ä¼å¨ç¨åºå¯å¨æ¶ç«å³çæï¼å¦ææ³é¿å
å»¶è¿ï¼å¯ä»¥å VM åæ° `-XX:BiasedLockingStartupDelay=0` æ¥ç¦ç¨å»¶è¿ãJDK 8 å»¶è¿ 4s å¼å¯ååéåå ï¼å¨åå¼å§æ§è¡ä»£ç æ¶ï¼ä¼æå¥½å¤çº¿ç¨æ¥æ¢éï¼å¦æå¼ååéæçåèéä½
* å½ä¸ä¸ªå¯¹è±¡å·²ç»è®¡ç®è¿ hashCodeï¼å°±å乿 æ³è¿å
¥ååç¶æäº
* æ·»å VM åæ° `-XX:-UseBiasedLocking` ç¦ç¨ååé
æ¤éååéçç¶æï¼
* è°ç¨å¯¹è±¡ç hashCodeï¼ååéç对象 MarkWord ä¸åå¨çæ¯çº¿ç¨ idï¼è°ç¨ hashCode 导è´ååé被æ¤é
* 彿å
¶å®çº¿ç¨ä½¿ç¨ååé对象æ¶ï¼ä¼å°ååéå级为轻é级é
* è°ç¨ wait/notifyï¼éè¦ç³è¯· Monitorï¼è¿å
¥ WaitSet
**æ¹éæ¤é**ï¼å¦æå¯¹è±¡è¢«å¤ä¸ªçº¿ç¨è®¿é®ï¼ä½æ²¡æç«äºï¼è¿æ¶ååäºçº¿ç¨ T1 çå¯¹è±¡ä»ææºä¼éæ°åå T2ï¼éååä¼é置对象ç Thread ID
* æ¹ééååï¼å½æ¤éååééå¼è¶
è¿ 20 次åï¼JVM ä¼è§å¾æ¯ä¸æ¯ååéäºï¼äºæ¯å¨ç»è¿äºå¯¹è±¡å éæ¶éæ°ååè³å é线ç¨
* æ¹éæ¤éï¼å½æ¤éååééå¼è¶
è¿ 40 次åï¼JVM ä¼è§å¾èªå·±ç¡®å®ååéäºï¼æ ¹æ¬å°±ä¸è¯¥ååï¼äºæ¯æ´ä¸ªç±»çææå¯¹è±¡é½ä¼å为ä¸å¯ååçï¼æ°å»ºçå¯¹è±¡ä¹æ¯ä¸å¯ååç
***
##### è½»é级é
ä¸ä¸ªå¯¹è±¡æå¤ä¸ªçº¿ç¨è¦å éï¼ä½å éçæ¶é´æ¯éå¼çï¼æ²¡æç«äºï¼ï¼å¯ä»¥ä½¿ç¨è½»éçº§éæ¥ä¼åï¼è½»é级é对使ç¨è
æ¯éæçï¼ä¸å¯è§ï¼
å¯éå
¥éï¼çº¿ç¨å¯ä»¥è¿å
¥ä»»ä½ä¸ä¸ªå®å·²ç»æ¥æçéæåæ¥çç代ç åï¼å¯éå
¥éæå¤§çä½ç¨æ¯**é¿å
æ»é**
è½»é级é卿²¡æç«äºæ¶ï¼ééå
¥æ¶ï¼ï¼æ¯æ¬¡éå
¥ä»ç¶éè¦æ§è¡ CAS æä½ï¼Java 6 æå¼å
¥çåå鿥ä¼å
ééå
¥å®ä¾ï¼
```java
static final Object obj = new Object();
public static void method1() {
synchronized( obj ) {
// 忥å A
method2();
}
}
public static void method2() {
synchronized( obj ) {
// 忥å B
}
}
```
* å建éè®°å½ï¼Lock Recordï¼å¯¹è±¡ï¼æ¯ä¸ªçº¿ç¨ç**æ 帧**é½ä¼å
å«ä¸ä¸ªéè®°å½çç»æï¼åå¨éå®å¯¹è±¡ç Mark Word

* 让éè®°å½ä¸ Object reference æåéä½ç对象ï¼å¹¶å°è¯ç¨ CAS æ¿æ¢ Object ç Mark Wordï¼å° Mark Word çå¼åå
¥éè®°å½
* 妿 CAS æ¿æ¢æåï¼å¯¹è±¡å¤´ä¸åå¨äºéè®°å½å°ååç¶æ 00ï¼è½»é级éï¼ ï¼è¡¨ç¤ºç±è¯¥çº¿ç¨ç»å¯¹è±¡å é

* 妿 CAS å¤±è´¥ï¼æä¸¤ç§æ
åµï¼
* 妿æ¯å
¶å®çº¿ç¨å·²ç»ææäºè¯¥ Object çè½»é级éï¼è¿æ¶è¡¨ææç«äºï¼è¿å
¥éè¨èè¿ç¨
* 妿æ¯çº¿ç¨èªå·±æ§è¡äº synchronized ééå
¥ï¼å°±æ·»å 䏿¡ Lock Record ä½ä¸ºéå
¥ç计æ°

* å½éåº synchronized 代ç åï¼è§£éæ¶ï¼
* 妿æåå¼ä¸º null çéè®°å½ï¼è¡¨ç¤ºæéå
¥ï¼è¿æ¶éç½®éè®°å½ï¼è¡¨ç¤ºéå
¥è®¡æ°å 1
* 妿éè®°å½çå¼ä¸ä¸º nullï¼è¿æ¶ä½¿ç¨ CAS **å° Mark Word ç弿¢å¤ç»å¯¹è±¡å¤´**
* æåï¼åè§£éæå
* 失败ï¼è¯´æè½»é级éè¿è¡äºéè¨èæå·²ç»å级为éé级éï¼è¿å
¥éé级éè§£éæµç¨
***
##### éè¨è
å¨å°è¯å è½»é级éçè¿ç¨ä¸ï¼CAS æä½æ æ³æåï¼å¯è½æ¯å
¶å®çº¿ç¨ä¸ºæ¤å¯¹è±¡å ä¸äºè½»é级éï¼æç«äºï¼ï¼è¿æ¶éè¦è¿è¡éè¨èï¼å°è½»é级éå为**éé级é**
* å½ Thread-1 è¿è¡è½»é级å éæ¶ï¼Thread-0 å·²ç»å¯¹è¯¥å¯¹è±¡å äºè½»é级é

* Thread-1 å è½»é级é失败ï¼è¿å
¥éè¨èæµç¨ï¼ä¸º Object 对象ç³è¯· Monitor éï¼**éè¿ Object 对象头è·åå°æé线ç¨**ï¼å° Monitor ç Owner 置为 Thread-0ï¼å° Object ç对象头æåéé级éå°åï¼ç¶åèªå·±è¿å
¥ Monitor ç EntryList BLOCKED

* å½ Thread-0 éåºåæ¥åè§£éæ¶ï¼ä½¿ç¨ CAS å° Mark Word ç弿¢å¤ç»å¯¹è±¡å¤´å¤±è´¥ï¼è¿æ¶è¿å
¥ééçº§è§£éæµç¨ï¼å³æç
§ Monitor å°åæ¾å° Monitor 对象ï¼è®¾ç½® Owner 为 nullï¼å¤é EntryList ä¸ BLOCKED 线ç¨
***
#### éä¼å
##### èªæé
éé级éç«äºæ¶ï¼å°è¯è·åéç线ç¨ä¸ä¼ç«å³é»å¡ï¼å¯ä»¥ä½¿ç¨**èªæ**ï¼é»è®¤ 10 æ¬¡ï¼æ¥è¿è¡ä¼åï¼éç¨å¾ªç¯çæ¹å¼å»å°è¯è·åé
注æï¼
* èªæå ç¨ CPU æ¶é´ï¼åæ ¸ CPU èªæå°±æ¯æµªè´¹æ¶é´ï¼å 为å䏿¶å»åªè½è¿è¡ä¸ä¸ªçº¿ç¨ï¼å¤æ ¸ CPU èªææè½åæ¥ä¼å¿
* èªæå¤±è´¥ç线ç¨ä¼è¿å
¥é»å¡ç¶æ
ä¼ç¹ï¼ä¸ä¼è¿å
¥é»å¡ç¶æï¼**åå°çº¿ç¨ä¸ä¸æåæ¢çæ¶è**
缺ç¹ï¼å½èªæç线ç¨è¶æ¥è¶å¤æ¶ï¼ä¼ä¸æçæ¶è CPU èµæº
èªæéæ
åµï¼
* èªææåçæ
åµï¼
* èªæå¤±è´¥çæ
åµï¼
èªæé说æï¼
* å¨ Java 6 ä¹åèªæéæ¯èªéåºçï¼æ¯å¦å¯¹è±¡ååç䏿¬¡èªææä½æåè¿ï¼é£ä¹è®¤ä¸ºè¿æ¬¡èªææåçå¯è½æ§ä¼é«ï¼å°±å¤èªæå 次ï¼åä¹ï¼å°±å°èªæçè³ä¸èªæï¼æ¯è¾æºè½
* Java 7 ä¹åä¸è½æ§å¶æ¯å¦å¼å¯èªæåè½ï¼ç± JVM æ§å¶
```java
//æåèªæé
public class SpinLock {
// æ³åè£
çæ¯Threadï¼ååå¼ç¨çº¿ç¨
AtomicReference atomicReference = new AtomicReference<>();
public void lock() {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + " come in");
//å¼å§èªæï¼ææå¼ä¸ºnullï¼æ´æ°å¼æ¯å½å线ç¨
while (!atomicReference.compareAndSet(null, thread)) {
Thread.sleep(1000);
System.out.println(thread.getName() + " æ£å¨èªæ");
}
System.out.println(thread.getName() + " èªææå");
}
public void unlock() {
Thread thread = Thread.currentThread();
//线ç¨ä½¿ç¨å®éæå¼ç¨å为null
atomicReference.compareAndSet(thread, null);
System.out.println(thread.getName() + " invoke unlock");
}
public static void main(String[] args) throws InterruptedException {
SpinLock lock = new SpinLock();
new Thread(() -> {
//å æé
lock.lock();
Thread.sleep(10000);
//éæ¾é
lock.unlock();
},"t1").start();
// 让mainçº¿ç¨æå1ç§ï¼ä½¿å¾t1线ç¨ï¼å
æ§è¡
Thread.sleep(1000);
new Thread(() -> {
lock.lock();
lock.unlock();
},"t2").start();
}
}
```
***
##### éæ¶é¤
鿶餿¯æå¯¹äºè¢«æ£æµåºä¸å¯è½åå¨ç«äºçå
±äº«æ°æ®çéè¿è¡æ¶é¤ï¼è¿æ¯ JVM **峿¶ç¼è¯å¨çä¼å**
éæ¶é¤ä¸»è¦æ¯éè¿**éé¸åæ**æ¥æ¯æï¼å¦æå ä¸çå
±äº«æ°æ®ä¸å¯è½éé¸åºå»è¢«å
¶å®çº¿ç¨è®¿é®å°ï¼é£ä¹å°±å¯ä»¥æå®ä»¬å½æç§ææ°æ®å¯¹å¾
ï¼ä¹å°±å¯ä»¥å°å®ä»¬çéè¿è¡æ¶é¤ï¼åæ¥æ¶é¤ï¼JVM éé¸åæï¼
***
##### éç²å
对ç¸åå¯¹è±¡å¤æ¬¡å éï¼å¯¼è´çº¿ç¨åç夿¬¡éå
¥ï¼é¢ç¹çå éæä½å°±ä¼å¯¼è´æ§è½æèï¼å¯ä»¥ä½¿ç¨éç²åæ¹å¼ä¼å
å¦æèææºæ¢æµå°ä¸ä¸²çæä½é½å¯¹åä¸ä¸ªå¯¹è±¡å éï¼å°ä¼æå éçèå´æ©å±ï¼ç²åï¼å°æ´ä¸ªæä½åºåçå¤é¨
* ä¸äºçèµ·æ¥æ²¡æå éç代ç ï¼å
¶å®éå¼çå äºå¾å¤éï¼
```java
public static String concatString(String s1, String s2, String s3) {
return s1 + s2 + s3;
}
```
* String æ¯ä¸ä¸ªä¸å¯åçç±»ï¼ç¼è¯å¨ä¼å¯¹ String çæ¼æ¥èªå¨ä¼åãå¨ JDK 1.5 ä¹åï¼è½¬å为 StringBuffer 对象çè¿ç» append() æä½ï¼æ¯ä¸ª append() æ¹æ³ä¸é½æä¸ä¸ªåæ¥å
```java
public static String concatString(String s1, String s2, String s3) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
sb.append(s3);
return sb.toString();
}
```
æ©å±å°ç¬¬ä¸ä¸ª append() æä½ä¹åç´è³æåä¸ä¸ª append() æä½ä¹åï¼åªéè¦å é䏿¬¡å°±å¯ä»¥
****
#### 夿é
夿ä¸ç¸å¹²çéï¼ä¸é´å¤§å±åæä¸¤ä¸ªåè½ç¡è§ãå¦ä¹ ï¼äºä¸ç¸å¹²ãç°å¨ä¸äººè¦å¦ä¹ ï¼ä¸äººè¦ç¡è§ï¼å¦æåªç¨ä¸é´å±åï¼ä¸ä¸ªå¯¹è±¡éï¼çè¯ï¼é£ä¹å¹¶å度å¾ä½
å°éçç²åº¦ç»åï¼
* 好å¤ï¼æ¯å¯ä»¥å¢å¼ºå¹¶å度
* åå¤ï¼å¦æä¸ä¸ªçº¿ç¨éè¦åæ¶è·å¾å¤æéï¼å°±å®¹æåçæ»é
è§£å³æ¹æ³ï¼åå¤å¤ä¸ªå¯¹è±¡é
```java
public static void main(String[] args) {
BigRoom bigRoom = new BigRoom();
new Thread(() -> { bigRoom.study(); }).start();
new Thread(() -> { bigRoom.sleep(); }).start();
}
class BigRoom {
private final Object studyRoom = new Object();
private final Object sleepRoom = new Object();
public void sleep() throws InterruptedException {
synchronized (sleepRoom) {
System.out.println("sleeping 2 å°æ¶");
Thread.sleep(2000);
}
}
public void study() throws InterruptedException {
synchronized (studyRoom) {
System.out.println("study 1 å°æ¶");
Thread.sleep(1000);
}
}
}
```
***
#### æ´»è·æ§
##### æ»é
###### å½¢æ
æ»éï¼å¤ä¸ªçº¿ç¨åæ¶è¢«é»å¡ï¼å®ä»¬ä¸çä¸ä¸ªæè
å
¨é¨é½å¨çå¾
æä¸ªèµæºè¢«éæ¾ï¼ç±äºçº¿ç¨è¢«æ éæå°é»å¡ï¼å æ¤ç¨åºä¸å¯è½æ£å¸¸ç»æ¢
Java æ»é产ççå个å¿
è¦æ¡ä»¶ï¼
1. äºæ¥æ¡ä»¶ï¼å³å½èµæºè¢«ä¸ä¸ªçº¿ç¨ä½¿ç¨ï¼å æï¼æ¶ï¼å«ç线ç¨ä¸è½ä½¿ç¨
2. ä¸å¯å¥å¤ºæ¡ä»¶ï¼èµæºè¯·æ±è
ä¸è½å¼ºå¶ä»èµæºå æè
æä¸å¤ºåèµæºï¼èµæºåªè½ç±èµæºå æè
主å¨éæ¾
3. 请æ±åä¿ææ¡ä»¶ï¼å³å½èµæºè¯·æ±è
å¨è¯·æ±å
¶ä»çèµæºçåæ¶ä¿æå¯¹åæèµæºçå æ
4. 循ç¯çå¾
æ¡ä»¶ï¼å³åå¨ä¸ä¸ªçå¾
循ç¯éåï¼p1 è¦ p2 çèµæºï¼p2 è¦ p1 çèµæºï¼å½¢æäºä¸ä¸ªçå¾
ç¯è·¯
å个æ¡ä»¶é½æç«çæ¶åï¼ä¾¿å½¢ææ»éãæ»éæ
åµä¸æç ´ä¸è¿°ä»»ä½ä¸ä¸ªæ¡ä»¶ï¼ä¾¿å¯è®©æ»éæ¶å¤±
```java
public class Dead {
public static Object resources1 = new Object();
public static Object resources2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
// 线ç¨1ï¼å ç¨èµæº1 ï¼è¯·æ±èµæº2
synchronized(resources1){
System.out.println("线ç¨1å·²ç»å ç¨äºèµæº1ï¼å¼å§è¯·æ±èµæº2");
Thread.sleep(2000);//伿¯ä¸¤ç§ï¼é²æ¢çº¿ç¨1ç´æ¥è¿è¡å®æã
//2ç§å
线ç¨2è¯å®å¯ä»¥éä½èµæº2
synchronized (resources2){
System.out.println("线ç¨1å·²ç»å ç¨äºèµæº2");
}
}).start();
new Thread(() -> {
// 线ç¨2ï¼å ç¨èµæº2 ï¼è¯·æ±èµæº1
synchronized(resources2){
System.out.println("线ç¨2å·²ç»å ç¨äºèµæº2ï¼å¼å§è¯·æ±èµæº1");
Thread.sleep(2000);
synchronized (resources1){
System.out.println("线ç¨2å·²ç»å ç¨äºèµæº1");
}
}}
}).start();
}
}
```
***
###### å®ä½
å®ä½æ»éçæ¹æ³ï¼
* ä½¿ç¨ jps å®ä½è¿ç¨ idï¼åç¨ `jstack id` å®ä½æ»éï¼æ¾å°æ»éç线ç¨å»æ¥çæºç ï¼è§£å³ä¼å
```sh
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001eb69000 nid=0xd40 waiting formonitor entry [0x000000001f54f000]
java.lang.Thread.State: BLOCKED (on object monitor)
#çç¥
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001eb69000 nid=0xd40 waiting for monitor entry [0x000000001f54f000]
java.lang.Thread.State: BLOCKED (on object monitor)
#çç¥
Found one Java-level deadlock:
===================================================
"Thread-1":
waiting to lock monitor 0x000000000361d378 (object 0x000000076b5bf1c0, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000361e768 (object 0x000000076b5bf1d0, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
- waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)
- locked <0x000000076b5bf1d0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"Thread-0":
at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)
- waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)
- locked <0x000000076b5bf1c0> (a java.lang.Object)
at thread.TestDeadLock$$Lambda$1/495053715
```
* Linux ä¸å¯ä»¥éè¿ top å
å®ä½å° CPU å ç¨é«ç Java è¿ç¨ï¼åå©ç¨ `top -Hp è¿ç¨id` æ¥å®ä½æ¯åªä¸ªçº¿ç¨ï¼æååç¨ jstack çè¾åºæ¥çåä¸ªçº¿ç¨æ
* é¿å
æ»éï¼é¿å
æ»éè¦æ³¨æå é顺åº
* å¯ä»¥ä½¿ç¨ jconsole å·¥å
·ï¼å¨ `jdk\bin` ç®å½ä¸
***
##### æ´»é
æ´»éï¼æçæ¯ä»»å¡æè
æ§è¡è
没æè¢«é»å¡ï¼ç±äºæäºæ¡ä»¶æ²¡ææ»¡è¶³ï¼å¯¼è´ä¸ç´éå¤å°è¯â失败âå°è¯â失败çè¿ç¨
两个线ç¨äºç¸æ¹å对æ¹çç»ææ¡ä»¶ï¼æåè°ä¹æ æ³ç»æï¼
```java
class TestLiveLock {
static volatile int count = 10;
static final Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
// ææåå° 0 éåºå¾ªç¯
while (count > 0) {
Thread.sleep(200);
count--;
System.out.println("线ç¨ä¸count:" + count);
}
}, "t1").start();
new Thread(() -> {
// ææè¶
è¿ 20 éåºå¾ªç¯
while (count < 20) {
Thread.sleep(200);
count++;
System.out.println("线ç¨äºcount:"+ count);
}
}, "t2").start();
}
}
```
***
##### 饥饿
饥饿ï¼ä¸ä¸ªçº¿ç¨ç±äºä¼å
级太ä½ï¼å§ç»å¾ä¸å° CPU è°åº¦æ§è¡ï¼ä¹ä¸è½å¤ç»æ
***
### wait-ify
#### åºæ¬ä½¿ç¨
éè¦è·å对象éåæå¯ä»¥è°ç¨ `é对象.wait()`ï¼notify éæºå¤éä¸ä¸ªçº¿ç¨ï¼notifyAll å¤éææçº¿ç¨å»ç«äº CPU
Object ç±» APIï¼
```java
public final void notify():å¤éæ£å¨çå¾
对象çè§å¨çå个线ç¨ã
public final void notifyAll():å¤éæ£å¨çå¾
对象çè§å¨çææçº¿ç¨ã
public final void wait():导è´å½å线ç¨çå¾
ï¼ç´å°å¦ä¸ä¸ªçº¿ç¨è°ç¨è¯¥å¯¹è±¡çnotify()æ¹æ³æ notifyAll()æ¹æ³ã
public final native void wait(long timeout):ææ¶éççå¾
, å°n毫ç§åç»æçå¾
ï¼ææ¯è¢«å¤é
```
说æï¼**wait æ¯æèµ·çº¿ç¨ï¼éè¦å¤éç齿¯æèµ·æä½**ï¼é»å¡çº¿ç¨å¯ä»¥èªå·±å»äºæ¢éï¼æèµ·ç线ç¨éè¦å¤éåå»äºæ¢é
å¯¹æ¯ sleep()ï¼
* åçä¸åï¼sleep() æ¹æ³æ¯å±äº Thread ç±»ï¼æ¯çº¿ç¨ç¨æ¥æ§å¶èªèº«æµç¨çï¼ä½¿æ¤çº¿ç¨æåæ§è¡ä¸æ®µæ¶é´èææ§è¡æºä¼è®©ç»å
¶ä»çº¿ç¨ï¼wait() æ¹æ³å±äº Object ç±»ï¼ç¨äºçº¿ç¨é´éä¿¡
* 对**éçå¤çæºå¶**ä¸åï¼è°ç¨ sleep() æ¹æ³çè¿ç¨ä¸ï¼çº¿ç¨ä¸ä¼éæ¾å¯¹è±¡éï¼å½è°ç¨ wait() æ¹æ³çæ¶åï¼çº¿ç¨ä¼æ¾å¼å¯¹è±¡éï¼è¿å
¥çå¾
æ¤å¯¹è±¡ççå¾
é宿± ï¼ä¸éæ¾éå
¶ä»çº¿ç¨æä¹æ¢å å°éæ§è¡å¤éæä½ï¼ï¼ä½æ¯é½ä¼éæ¾ CPU
* 使ç¨åºåä¸åï¼wait() æ¹æ³å¿
é¡»æ¾å¨**忥æ§å¶æ¹æ³å忥代ç åï¼å
è·åéï¼**ä¸ä½¿ç¨ï¼sleep() æ¹æ³åå¯ä»¥æ¾å¨ä»»ä½å°æ¹ä½¿ç¨
åºå±åçï¼
* Owner 线ç¨åç°æ¡ä»¶ä¸æ»¡è¶³ï¼è°ç¨ wait æ¹æ³ï¼å³å¯è¿å
¥ WaitSet å为 WAITING ç¶æ
* BLOCKED å WAITING ç线ç¨é½å¤äºé»å¡ç¶æï¼ä¸å ç¨ CPU æ¶é´ç
* BLOCKED 线ç¨ä¼å¨ Owner 线ç¨éæ¾éæ¶å¤é
* WAITING 线ç¨ä¼å¨ Owner 线ç¨è°ç¨ notify æ notifyAll æ¶å¤éï¼å¤éå并䏿å³è
ç«å»è·å¾éï¼**éè¦è¿å
¥ EntryList éæ°ç«äº**

***
#### 代ç ä¼å
èåå¤éï¼notify åªè½éæºå¤éä¸ä¸ª WaitSet ä¸ç线ç¨ï¼è¿æ¶å¦ææå
¶å®çº¿ç¨ä¹å¨çå¾
ï¼é£ä¹å°±å¯è½å¤éä¸äºæ£ç¡®ç线ç¨
è§£å³æ¹æ³ï¼éç¨ notifyAll
notifyAll ä»
è§£å³æä¸ªçº¿ç¨çå¤éé®é¢ï¼ä½¿ç¨ if + wait 夿ä»
æä¸æ¬¡æºä¼ï¼ä¸æ¦æ¡ä»¶ä¸æç«ï¼æ æ³éæ°å¤æ
è§£å³æ¹æ³ï¼ç¨ while + waitï¼å½æ¡ä»¶ä¸æç«ï¼å次 wait
```java
@Slf4j(topic = "c.demo")
public class demo {
static final Object room = new Object();
static boolean hasCigarette = false; //ææ²¡æç
static boolean hasTakeout = false;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
synchronized (room) {
log.debug("æç没ï¼[{}]", hasCigarette);
while (!hasCigarette) {//while鲿¢èåå¤é
log.debug("没çï¼å
æä¼ï¼");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("æç没ï¼[{}]", hasCigarette);
if (hasCigarette) {
log.debug("å¯ä»¥å¼å§å¹²æ´»äº");
} else {
log.debug("æ²¡å¹²ææ´»...");
}
}
}, "å°å").start();
new Thread(() -> {
synchronized (room) {
Thread thread = Thread.currentThread();
log.debug("å¤åéå°æ²¡ï¼[{}]", hasTakeout);
if (!hasTakeout) {
log.debug("没å¤åï¼å
æä¼ï¼");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("å¤åéå°æ²¡ï¼[{}]", hasTakeout);
if (hasTakeout) {
log.debug("å¯ä»¥å¼å§å¹²æ´»äº");
} else {
log.debug("æ²¡å¹²ææ´»...");
}
}
}, "å°å¥³").start();
Thread.sleep(1000);
new Thread(() -> {
// è¿éè½ä¸è½å synchronized (room)ï¼
synchronized (room) {
hasTakeout = true;
//log.debug("çå°äºå¢ï¼");
log.debug("å¤åå°äºå¢ï¼");
room.notifyAll();
}
}, "éå¤åç").start();
}
}
```
****
### park-un
LockSupport æ¯ç¨æ¥å建éåå
¶ä»åæ¥ç±»ç**线ç¨åè¯**
LockSupport ç±»æ¹æ³ï¼
* `LockSupport.park()`ï¼æåå½å线ç¨ï¼æèµ·åè¯
* `LockSupport.unpark(æåç线ç¨å¯¹è±¡)`ï¼æ¢å¤æä¸ªçº¿ç¨çè¿è¡
```java
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("start..."); //1
Thread.sleep(1000);// Thread.sleep(3000)
// å
park å unpark åå
unpark å park ææä¸æ ·ï¼é½ä¼ç´æ¥æ¢å¤çº¿ç¨çè¿è¡
System.out.println("park..."); //2
LockSupport.park();
System.out.println("resume...");//4
},"t1");
t1.start();
Thread.sleep(2000);
System.out.println("unpark..."); //3
LockSupport.unpark(t1);
}
```
LockSupport åºç°å°±æ¯ä¸ºäºå¢å¼º wait & notify çåè½ï¼
* waitï¼notify å notifyAll å¿
é¡»é
å Object Monitor ä¸èµ·ä½¿ç¨ï¼è parkãunpark ä¸éè¦
* park & unpark **以线ç¨ä¸ºåä½**æ¥é»å¡åå¤é线ç¨ï¼è notify åªè½éæºå¤éä¸ä¸ªçå¾
线ç¨ï¼notifyAll æ¯å¤éææçå¾
线ç¨
* park & unpark å¯ä»¥å
unparkï¼è wait & notify ä¸è½å
notifyãç±»æ¯ç产æ¶è´¹ï¼å
æ¶è´¹åç°æäº§åå°±æ¶è´¹ï¼æ²¡æå°±çå¾
ï¼å
çäº§å°±ç´æ¥äº§çååï¼ç¶å线ç¨ç´æ¥æ¶è´¹
* wait ä¼éæ¾éèµæºè¿å
¥çå¾
éåï¼**park ä¸ä¼éæ¾éèµæº**ï¼åªè´è´£é»å¡å½å线ç¨ï¼ä¼éæ¾ CPU
åçï¼ç±»ä¼¼ç产è
æ¶è´¹è
* å
parkï¼
1. å½å线ç¨è°ç¨ Unsafe.park() æ¹æ³
2. æ£æ¥ _counter ï¼æ¬æ
åµä¸º 0ï¼è¿æ¶è·å¾ _mutex äºæ¥é
3. 线ç¨è¿å
¥ _cond æ¡ä»¶åéæèµ·
4. è°ç¨ Unsafe.unpark(Thread_0) æ¹æ³ï¼è®¾ç½® _counter 为 1
5. å¤é _cond æ¡ä»¶åéä¸ç Thread_0ï¼Thread_0 æ¢å¤è¿è¡ï¼è®¾ç½® _counter 为 0

* å
unparkï¼
1. è°ç¨ Unsafe.unpark(Thread_0) æ¹æ³ï¼è®¾ç½® _counter 为 1
2. å½å线ç¨è°ç¨ Unsafe.park() æ¹æ³
3. æ£æ¥ _counter ï¼æ¬æ
åµä¸º 1ï¼è¿æ¶çº¿ç¨æ éæèµ·ï¼ç»§ç»è¿è¡ï¼è®¾ç½® _counter 为 0

***
### å®å
¨åæ
æååéåéæåéï¼
* 妿å®ä»¬æ²¡æå
±äº«ï¼å线ç¨å®å
¨
* 妿å®ä»¬è¢«å
±äº«äºï¼æ ¹æ®å®ä»¬çç¶ææ¯å¦è½å¤æ¹åï¼åä¸¤ç§æ
åµï¼
* å¦æåªæè¯»æä½ï¼å线ç¨å®å
¨
* 妿æè¯»åæä½ï¼åè¿æ®µä»£ç æ¯ä¸´çåºï¼éè¦èè线ç¨å®å
¨é®é¢
å±é¨åéï¼
* å±é¨åéæ¯çº¿ç¨å®å
¨ç
* å±é¨åéå¼ç¨ç对象ä¸ä¸å®çº¿ç¨å®å
¨ï¼éé¸åæï¼ï¼
* å¦æè¯¥å¯¹è±¡æ²¡æéç¦»æ¹æ³çä½ç¨è®¿é®ï¼å®æ¯çº¿ç¨å®å
¨çï¼æ¯ä¸ä¸ªæ¹æ³æä¸ä¸ªæ 帧ï¼
* å¦æè¯¥å¯¹è±¡éç¦»æ¹æ³çä½ç¨èå´ï¼éè¦èè线ç¨å®å
¨é®é¢ï¼æ´é²å¼ç¨ï¼
常è§çº¿ç¨å®å
¨ç±»ï¼StringãIntegerãStringBufferãRandomãVectorãHashtableãjava.util.concurrent å
* 线ç¨å®å
¨çæ¯æï¼å¤ä¸ªçº¿ç¨è°ç¨å®ä»¬åä¸ä¸ªå®ä¾çæä¸ªæ¹æ³æ¶ï¼æ¯çº¿ç¨å®å
¨ç
* **æ¯ä¸ªæ¹æ³æ¯ååçï¼ä½å¤ä¸ªæ¹æ³çç»å䏿¯ååç**ï¼åªè½ä¿è¯è°ç¨çæ¹æ³å
é¨å®å
¨ï¼
```java
Hashtable table = new Hashtable();
// 线ç¨1ï¼çº¿ç¨2
if(table.get("key") == null) {
table.put("key", value);
}
```
æ ç¶æç±»çº¿ç¨å®å
¨ï¼å°±æ¯æ²¡ææååéçç±»
ä¸å¯å类线ç¨å®å
¨ï¼StringãInteger ç齿¯ä¸å¯åç±»ï¼**å
é¨çç¶æä¸å¯ä»¥æ¹å**ï¼æä»¥æ¹æ³æ¯çº¿ç¨å®å
¨
* replace çæ¹æ³åºå±æ¯æ°å»ºä¸ä¸ªå¯¹è±¡ï¼å¤å¶è¿å»
```java
Map map = new HashMap<>(); // 线ç¨ä¸å®å
¨
String S1 = "..."; // 线ç¨å®å
¨
final String S2 = "..."; // 线ç¨å®å
¨
Date D1 = new Date(); // 线ç¨ä¸å®å
¨
final Date D2 = new Date(); // 线ç¨ä¸å®å
¨ï¼final让D2å¼ç¨ç对象ä¸è½åï¼ä½å¯¹è±¡çå
容å¯ä»¥å
```
æ½è±¡æ¹æ³å¦ææåæ°ï¼è¢«éååè¡ä¸ºä¸ç¡®å®å¯è½é æçº¿ç¨ä¸å®å
¨ï¼è¢«ç§°ä¹ä¸ºå¤ææ¹æ³ï¼`public abstract foo(Student s);`
***
### åæ¥æ¨¡å¼
#### ä¿æ¤æ§æå
##### åä»»å¡ç
Guarded Suspensionï¼ç¨å¨ä¸ä¸ªçº¿ç¨çå¾
å¦ä¸ä¸ªçº¿ç¨çæ§è¡ç»æ
* æä¸ä¸ªç»æéè¦ä»ä¸ä¸ªçº¿ç¨ä¼ éå°å¦ä¸ä¸ªçº¿ç¨ï¼è®©å®ä»¬å
³èåä¸ä¸ª GuardedObject
* 妿æç»æä¸æä»ä¸ä¸ªçº¿ç¨å°å¦ä¸ä¸ªçº¿ç¨é£ä¹å¯ä»¥ä½¿ç¨æ¶æ¯éåï¼è§ç产è
/æ¶è´¹è
ï¼
* JDK ä¸ï¼join çå®ç°ãFuture çå®ç°ï¼éç¨çå°±æ¯æ¤æ¨¡å¼

```java
public static void main(String[] args) {
GuardedObject object = new GuardedObjectV2();
new Thread(() -> {
sleep(1);
object.complete(Arrays.asList("a", "b", "c"));
}).start();
Object response = object.get(2500);
if (response != null) {
log.debug("get response: [{}] lines", ((List) response).size());
} else {
log.debug("can't get response");
}
}
class GuardedObject {
private Object response;
private final Object lock = new Object();
//è·åç»æ
//timeout :æå¤§çå¾
æ¶é´
public Object get(long millis) {
synchronized (lock) {
// 1) è®°å½æåæ¶é´
long begin = System.currentTimeMillis();
// 2) å·²ç»ç»åçæ¶é´
long timePassed = 0;
while (response == null) {
// 4) å设 millis æ¯ 1000ï¼ç»æå¨ 400 æ¶å¤éäºï¼é£ä¹è¿æ 600 è¦ç
long waitTime = millis - timePassed;
log.debug("waitTime: {}", waitTime);
//ç»åæ¶é´è¶
è¿æå¤§çå¾
æ¶é´éåºå¾ªç¯
if (waitTime <= 0) {
log.debug("break...");
break;
}
try {
lock.wait(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 3) 妿æå被å¤éï¼è¿æ¶å·²ç»ç»åçæ¶é´å设为 400
timePassed = System.currentTimeMillis() - begin;
log.debug("timePassed: {}, object is null {}",
timePassed, response == null);
}
return response;
}
}
//产çç»æ
public void complete(Object response) {
synchronized (lock) {
// æ¡ä»¶æ»¡è¶³ï¼éç¥çå¾
线ç¨
this.response = response;
log.debug("notify...");
lock.notifyAll();
}
}
}
```
##### å¤ä»»å¡ç
å¤ä»»å¡çä¿æ¤æ§æåï¼

```java
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
new People().start();
}
Thread.sleep(1000);
for (Integer id : Mailboxes.getIds()) {
new Postman(id, id + "å·å¿«éå°äº").start();
}
}
@Slf4j(topic = "c.People")
class People extends Thread{
@Override
public void run() {
// æ¶ä¿¡
GuardedObject guardedObject = Mailboxes.createGuardedObject();
log.debug("å¼å§æ¶ä¿¡i d:{}", guardedObject.getId());
Object mail = guardedObject.get(5000);
log.debug("æ¶å°ä¿¡id:{}ï¼å
容:{}", guardedObject.getId(),mail);
}
}
class Postman extends Thread{
private int id;
private String mail;
//æé æ¹æ³
@Override
public void run() {
GuardedObject guardedObject = Mailboxes.getGuardedObject(id);
log.debug("å¼å§éä¿¡i d:{}ï¼å
容:{}", guardedObject.getId(),mail);
guardedObject.complete(mail);
}
}
class Mailboxes {
private static Map boxes = new Hashtable<>();
private static int id = 1;
//产çå¯ä¸çid
private static synchronized int generateId() {
return id++;
}
public static GuardedObject getGuardedObject(int id) {
return boxes.remove(id);
}
public static GuardedObject createGuardedObject() {
GuardedObject go = new GuardedObject(generateId());
boxes.put(go.getId(), go);
return go;
}
public static Set getIds() {
return boxes.keySet();
}
}
class GuardedObject {
//æ è¯ï¼Guarded Object
private int id;//æ·»å get setæ¹æ³
}
```
****
#### 顺åºè¾åº
顺åºè¾åº 2 1
```java
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
//try { Thread.sleep(1000); } catch (InterruptedException e) { }
// 彿²¡æè®¸å¯æ¶ï¼å½åçº¿ç¨æåè¿è¡ï¼æè®¸å¯æ¶ï¼ç¨æè¿ä¸ªè®¸å¯ï¼å½åçº¿ç¨æ¢å¤è¿è¡
LockSupport.park();
System.out.println("1");
}
});
Thread t2 = new Thread(() -> {
while (true) {
System.out.println("2");
// ç»çº¿ç¨ t1 åæ¾ã许å¯ãï¼å¤æ¬¡è¿ç»è°ç¨ unpark åªä¼åæ¾ä¸ä¸ªã许å¯ãï¼
LockSupport.unpark(t1);
try { Thread.sleep(500); } catch (InterruptedException e) { }
}
});
t1.start();
t2.start();
}
```
***
#### 交æ¿è¾åº
è¿ç»è¾åº 5 次 abc
```java
public class day2_14 {
public static void main(String[] args) throws InterruptedException {
AwaitSignal awaitSignal = new AwaitSignal(5);
Condition a = awaitSignal.newCondition();
Condition b = awaitSignal.newCondition();
Condition c = awaitSignal.newCondition();
new Thread(() -> {
awaitSignal.print("a", a, b);
}).start();
new Thread(() -> {
awaitSignal.print("b", b, c);
}).start();
new Thread(() -> {
awaitSignal.print("c", c, a);
}).start();
Thread.sleep(1000);
awaitSignal.lock();
try {
a.signal();
} finally {
awaitSignal.unlock();
}
}
}
class AwaitSignal extends ReentrantLock {
private int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
//åæ°1ï¼æå°å
容 åæ°äºï¼æ¡ä»¶åé åæ°äºï¼å¤éä¸ä¸ä¸ª
public void print(String str, Condition condition, Condition next) {
for (int i = 0; i < loopNumber; i++) {
lock();
try {
condition.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
}
```
***
### 弿¥æ¨¡å¼
#### ä¼ ç»ç
弿¥æ¨¡å¼ä¹ç产è
/æ¶è´¹è
ï¼
```java
class ShareData {
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment() throws Exception{
// 忥代ç åï¼å é
lock.lock();
try {
// 夿 鲿¢èåå¤é
while(number != 0) {
// çå¾
ä¸è½ç产
condition.await();
}
// 干活
number++;
System.out.println(Thread.currentThread().getName() + "\t " + number);
// éç¥ å¤é
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement() throws Exception{
// 忥代ç åï¼å é
lock.lock();
try {
// 夿 鲿¢èåå¤é
while(number == 0) {
// çå¾
ä¸è½æ¶è´¹
condition.await();
}
// 干活
number--;
System.out.println(Thread.currentThread().getName() + "\t " + number);
// éç¥ å¤é
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class TraditionalProducerConsumer {
public static void main(String[] args) {
ShareData shareData = new ShareData();
// t1线ç¨ï¼ç产
new Thread(() -> {
for (int i = 0; i < 5; i++) {
shareData.increment();
}
}, "t1").start();
// t2线ç¨ï¼æ¶è´¹
new Thread(() -> {
for (int i = 0; i < 5; i++) {
shareData.decrement();
}
}, "t2").start();
}
}
```
#### æ¹è¿ç
弿¥æ¨¡å¼ä¹ç产è
/æ¶è´¹è
ï¼
* æ¶è´¹éåå¯ä»¥ç¨æ¥å¹³è¡¡çäº§åæ¶è´¹ç线ç¨èµæºï¼ä¸éè¦äº§çç»æåæ¶è´¹ç»æç线ç¨ä¸ä¸å¯¹åº
* ç产è
ä»
è´è´£äº§çç»ææ°æ®ï¼ä¸å
³å¿æ°æ®è¯¥å¦ä½å¤çï¼èæ¶è´¹è
ä¸å¿å¤çç»ææ°æ®
* æ¶æ¯é忝æå®¹ééå¶çï¼æ»¡æ¶ä¸ä¼åå å
¥æ°æ®ï¼ç©ºæ¶ä¸ä¼åæ¶èæ°æ®
* JDK ä¸åç§é»å¡éåï¼éç¨çå°±æ¯è¿ç§æ¨¡å¼

```java
public class demo {
public static void main(String[] args) {
MessageQueue queue = new MessageQueue(2);
for (int i = 0; i < 3; i++) {
int id = i;
new Thread(() -> {
queue.put(new Message(id,"å¼"+id));
}, "ç产è
" + i).start();
}
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
Message message = queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"æ¶è´¹è
").start();
}
}
//æ¶æ¯éåç±»ï¼Javaé´çº¿ç¨ä¹é´éä¿¡
class MessageQueue {
private LinkedList list = new LinkedList<>();//æ¶æ¯çéåéå
private int capacity;//éå容é
public MessageQueue(int capacity) {
this.capacity = capacity;
}
//è·åæ¶æ¯
public Message take() {
//æ£æ¥é忝å¦ä¸ºç©º
synchronized (list) {
while (list.isEmpty()) {
try {
sout(Thread.currentThread().getName() + ":éåä¸ºç©ºï¼æ¶è´¹è
线ç¨çå¾
");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//ä»éåç头é¨è·åæ¶æ¯è¿å
Message message = list.removeFirst();
sout(Thread.currentThread().getName() + "ï¼å·²æ¶è´¹æ¶æ¯--" + message);
list.notifyAll();
return message;
}
}
//åå
¥æ¶æ¯
public void put(Message message) {
synchronized (list) {
//æ£æ¥é忝妿»¡
while (list.size() == capacity) {
try {
sout(Thread.currentThread().getName()+":éå为已满ï¼ç产è
线ç¨çå¾
");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//å°æ¶æ¯å å
¥éåå°¾é¨
list.addLast(message);
sout(Thread.currentThread().getName() + ":å·²çäº§æ¶æ¯--" + message);
list.notifyAll();
}
}
}
final class Message {
private int id;
private Object value;
//get set
}
```
***
#### é»å¡éå
```java
public static void main(String[] args) {
ExecutorService consumer = Executors.newFixedThreadPool(1);
ExecutorService producer = Executors.newFixedThreadPool(1);
BlockingQueue queue = new SynchronousQueue<>();
producer.submit(() -> {
try {
System.out.println("ç产...");
Thread.sleep(1000);
queue.put(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
consumer.submit(() -> {
try {
System.out.println("çå¾
æ¶è´¹...");
Integer result = queue.take();
System.out.println("ç»æä¸º:" + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
```
****
## å
å
### JMM
#### å
忍¡å
Java å
忍¡åæ¯ Java Memory Modelï¼JMMï¼ï¼æ¬èº«æ¯ä¸ç§**æ½è±¡çæ¦å¿µ**ï¼å®é
ä¸å¹¶ä¸åå¨ï¼æè¿°çæ¯ä¸ç»è§åæè§èï¼éè¿è¿ç»è§èå®ä¹äºç¨åºä¸å个åéï¼å
æ¬å®ä¾å段ï¼éæåæ®µåæææ°ç»å¯¹è±¡çå
ç´ ï¼çè®¿é®æ¹å¼
JMM ä½ç¨ï¼
* å±è½åç§ç¡¬ä»¶åæä½ç³»ç»çå
å访é®å·®å¼ï¼å®ç°è®© Java ç¨åºå¨åç§å¹³å°ä¸é½è½è¾¾å°ä¸è´çå
åè®¿é®ææ
* è§å®äºçº¿ç¨åå
åä¹é´çä¸äºå
³ç³»
æ ¹æ® JMM ç设计ï¼ç³»ç»åå¨ä¸ä¸ªä¸»å
åï¼Main Memoryï¼ï¼Java 䏿æåéé½åå¨å¨ä¸»åä¸ï¼å¯¹äºææçº¿ç¨é½æ¯å
±äº«çï¼æ¯æ¡çº¿ç¨é½æèªå·±çå·¥ä½å
åï¼Working Memoryï¼ï¼å·¥ä½å
åä¸ä¿åçæ¯ä¸»å䏿äº**åéçæ·è´**ï¼çº¿ç¨å¯¹ææåéçæä½é½æ¯å
对åéè¿è¡æ·è´ï¼ç¶åå¨å·¥ä½å
åä¸è¿è¡ï¼ä¸è½ç´æ¥æä½ä¸»å
åä¸çåéï¼çº¿ç¨ä¹é´æ æ³ç¸äºç´æ¥è®¿é®ï¼çº¿ç¨é´çéä¿¡ï¼ä¼ éï¼å¿
é¡»éè¿ä¸»å
忥宿

主å
ååå·¥ä½å
åï¼
* 主å
åï¼è®¡ç®æºçå
åï¼ä¹å°±æ¯ç»å¸¸æå°ç 8G å
åï¼16G å
åï¼å卿æå
±äº«åéçå¼
* å·¥ä½å
åï¼åå¨è¯¥çº¿ç¨ä½¿ç¨å°çå
±äº«åéå¨ä¸»å
åççå¼ç坿¬æ·è´
**JVM å JMM ä¹é´çå
³ç³»**ï¼JMM ä¸ç主å
åãå·¥ä½å
åä¸ JVM ä¸ç Java å ãæ ãæ¹æ³åºç并䏿¯åä¸ä¸ªå±æ¬¡çå
åååï¼è¿ä¸¤è
åºæ¬ä¸æ¯æ²¡æå
³ç³»çï¼å¦æä¸¤è
ä¸å®è¦å强对åºèµ·æ¥ï¼
* 主å
å主è¦å¯¹åºäº Java å ä¸ç对象å®ä¾æ°æ®é¨åï¼èå·¥ä½å
åå对åºäºèææºæ ä¸çé¨ååºå
* 仿´ä½å±æ¬¡ä¸è¯´ï¼ä¸»å
åç´æ¥å¯¹åºäºç©ç硬件çå
åï¼å·¥ä½å
å对åºå¯åå¨åé«éç¼å
***
#### å
å交äº
Java å
忍¡åå®ä¹äº 8 个æä½æ¥å®æä¸»å
ååå·¥ä½å
åçäº¤äºæä½ï¼æ¯ä¸ªæä½é½æ¯**åå**ç
éåååå®ï¼æ²¡æè¢« volatile 修饰ç longãdouble å¤ï¼é»è®¤æç
§ä¸¤æ¬¡ 32 ä½çæä½
* lockï¼ä½ç¨äºä¸»å
åï¼å°ä¸ä¸ªåéæ è¯ä¸ºè¢«ä¸ä¸ªçº¿ç¨ç¬å ç¶æï¼å¯¹åº monitorenterï¼
* unclockï¼ä½ç¨äºä¸»å
åï¼å°ä¸ä¸ªåéä»ç¬å ç¶æéæ¾åºæ¥ï¼éæ¾åçåéæå¯ä»¥è¢«å
¶ä»çº¿ç¨éå®ï¼å¯¹åº monitorexitï¼
* readï¼ä½ç¨äºä¸»å
åï¼æä¸ä¸ªåéçå¼ä»ä¸»å
åä¼ è¾å°å·¥ä½å
åä¸
* loadï¼ä½ç¨äºå·¥ä½å
åï¼å¨ read ä¹åæ§è¡ï¼æ read å¾å°ç弿¾å
¥å·¥ä½å
åçåé坿¬ä¸
* useï¼ä½ç¨äºå·¥ä½å
åï¼æå·¥ä½å
åä¸ä¸ä¸ªåéçå¼ä¼ éç»**æ§è¡å¼æ**ï¼æ¯å½éå°ä¸ä¸ªä½¿ç¨å°åéçæä½æ¶é½è¦ä½¿ç¨è¯¥æä»¤
* assignï¼ä½ç¨äºå·¥ä½å
åï¼æä»æ§è¡å¼ææ¥æ¶å°çä¸ä¸ªå¼èµç»å·¥ä½å
åçåé
* storeï¼ä½ç¨äºå·¥ä½å
åï¼æå·¥ä½å
åçä¸ä¸ªåéçå¼ä¼ éå°ä¸»å
åä¸
* writeï¼ä½ç¨äºä¸»å
åï¼å¨ store ä¹åæ§è¡ï¼æ store å¾å°ç弿¾å
¥ä¸»å
åçåéä¸
åèæç« ï¼https://github.com/CyC2018/CS-Notes/blob/master/notes/Java%20%E5%B9%B6%E5%8F%91.md
***
#### ä¸å¤§ç¹æ§
##### å¯è§æ§
å¯è§æ§ï¼æ¯æå½å¤ä¸ªçº¿ç¨è®¿é®åä¸ä¸ªåéæ¶ï¼ä¸ä¸ªçº¿ç¨ä¿®æ¹äºè¿ä¸ªåéçå¼ï¼å
¶ä»çº¿ç¨è½å¤ç«å³çå¾å°ä¿®æ¹çå¼
åå¨ä¸å¯è§é®é¢çæ ¹æ¬åå æ¯ç±äºç¼åçåå¨ï¼çº¿ç¨ææçæ¯å
±äº«åéç坿¬ï¼æ æ³æç¥å
¶ä»çº¿ç¨å¯¹äºå
±äº«åéçæ´æ¹ï¼å¯¼è´è¯»åçå¼ä¸æ¯ææ°çã使¯ final 修饰çå鿝**ä¸å¯å**çï¼å°±ç®æç¼åï¼ä¹ä¸ä¼åå¨ä¸å¯è§çé®é¢
main 线ç¨å¯¹ run åéçä¿®æ¹å¯¹äº t 线ç¨ä¸å¯è§ï¼å¯¼è´äº t çº¿ç¨æ æ³åæ¢ï¼
```java
static boolean run = true; //æ·»å volatile
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while(run){
// ....
}
});
t.start();
sleep(1);
run = false; // 线ç¨tä¸ä¼å¦é¢æ³çå䏿¥
}
```
åå ï¼
* åå§ç¶æï¼ t 线ç¨åå¼å§ä»ä¸»å
å读åäº run çå¼å°å·¥ä½å
å
* å 为 t 线ç¨è¦é¢ç¹ä»ä¸»å
åä¸è¯»å run çå¼ï¼JIT ç¼è¯å¨ä¼å° run çå¼ç¼åè³èªå·±å·¥ä½å
åä¸çé«éç¼åä¸ï¼åå°å¯¹ä¸»åä¸ run ç访é®ï¼æé«æç
* 1 ç§ä¹åï¼main 线ç¨ä¿®æ¹äº run çå¼ï¼å¹¶åæ¥è³ä¸»åï¼è t æ¯ä»èªå·±å·¥ä½å
åä¸çé«éç¼åä¸è¯»åè¿ä¸ªåéçå¼ï¼ç»ææ°¸è¿æ¯æ§å¼

***
##### ååæ§
ååæ§ï¼ä¸å¯åå²ï¼å®æ´æ§ï¼ä¹å°±æ¯è¯´æä¸ªçº¿ç¨æ£å¨åæä¸ªå
·ä½ä¸å¡æ¶ï¼ä¸é´ä¸å¯ä»¥è¢«åå²ï¼éè¦å
·ä½å®æï¼è¦ä¹åæ¶æåï¼è¦ä¹åæ¶å¤±è´¥ï¼ä¿è¯æä»¤ä¸ä¼åå°çº¿ç¨ä¸ä¸æåæ¢çå½±å
å®ä¹ååæä½ç使ç¨è§åï¼
1. ä¸å
许 read å loadãstore å write æä½ä¹ä¸åç¬åºç°ï¼å¿
é¡»é¡ºåºæ§è¡ï¼ä½æ¯ä¸è¦æ±è¿ç»
1. ä¸å
许ä¸ä¸ªçº¿ç¨ä¸¢å¼ assign æä½ï¼å¿
须忥å主å
1. ä¸å
许ä¸ä¸ªçº¿ç¨æ åå å°ï¼æ²¡æåçè¿ä»»ä½ assign æä½ï¼ææ°æ®ä»å·¥ä½å
å忥ä¼ä¸»å
åä¸
2. ä¸ä¸ªæ°çåéåªè½å¨ä¸»å
åä¸è¯çï¼ä¸å
许å¨å·¥ä½å
åä¸ç´æ¥ä½¿ç¨ä¸ä¸ªæªè¢«åå§åï¼assign æè
loadï¼çåéï¼å³å¯¹ä¸ä¸ªåé宿½ use å store æä½ä¹åï¼å¿
é¡»å
èªè¡ assign å load æä½
3. ä¸ä¸ªåéå¨å䏿¶å»åªå
è®¸ä¸æ¡çº¿ç¨å¯¹å
¶è¿è¡ lock æä½ï¼ä½ lock æä½å¯ä»¥è¢«åä¸çº¿ç¨é夿§è¡å¤æ¬¡ï¼å¤æ¬¡æ§è¡ lock åï¼åªæ**æ§è¡ç¸å次æ°ç unlock** æä½ï¼åéæä¼è¢«è§£éï¼**lock å unlock å¿
é¡»æå¯¹åºç°**
4. 妿坹ä¸ä¸ªåéæ§è¡ lock æä½ï¼å°ä¼**æ¸
空工ä½å
å䏿¤åéçå¼**ï¼å¨æ§è¡å¼æä½¿ç¨è¿ä¸ªåéä¹åéè¦éæ°ä»ä¸»åå è½½
5. 妿ä¸ä¸ªåéäºå
没æè¢« lock æä½éå®ï¼åä¸å
许æ§è¡ unlock æä½ï¼ä¹ä¸å
è®¸å» unlock ä¸ä¸ªè¢«å
¶ä»çº¿ç¨éå®çåé
6. 对ä¸ä¸ªåéæ§è¡ unlock æä½ä¹åï¼å¿
é¡»**å
ææ¤åé忥å°ä¸»å
å**ä¸ï¼æ§è¡ store å write æä½ï¼
***
##### æåºæ§
æåºæ§ï¼å¨æ¬çº¿ç¨å
è§å¯ï¼æææä½é½æ¯æåºçï¼å¨ä¸ä¸ªçº¿ç¨è§å¯å¦ä¸ä¸ªçº¿ç¨ï¼æææä½é½æ¯æ åºçï¼æ åºæ¯å 为åçäºæä»¤éæåº
CPU çåºæ¬å·¥ä½æ¯æ§è¡åå¨çæä»¤åºåï¼å³ç¨åºï¼ç¨åºçæ§è¡è¿ç¨å®é
䏿¯ä¸æå°ååºæä»¤ãåææä»¤ãæ§è¡æä»¤çè¿ç¨ï¼ä¸ºäºæé«æ§è½ï¼ç¼è¯å¨åå¤çå¨ä¼å¯¹æä»¤éæï¼ä¸è¬å为以ä¸ä¸ç§ï¼
```java
æºä»£ç -> ç¼è¯å¨ä¼åçéæ -> æä»¤å¹¶è¡çéæ -> å
åç³»ç»çéæ -> æç»æ§è¡æä»¤
```
ç°ä»£ CPU æ¯æå¤çº§æä»¤æµæ°´çº¿ï¼å 乿æçå¯â¢è¯ºä¼æ¼åè®¡ç®æºç CPUï¼å
¶å·¥ä½é½å¯ä»¥å为 5 ä¸ªé¶æ®µï¼åæä»¤ãæä»¤è¯ç ãæ§è¡æä»¤ã访ååæ°åç»æååï¼å¯ä»¥ç§°ä¹ä¸º**äºçº§æä»¤æµæ°´çº¿**ãCPU å¯ä»¥å¨ä¸ä¸ªæ¶é卿å
ï¼åæ¶è¿è¡äºæ¡æä»¤ç**ä¸åé¶æ®µ**ï¼æ¯ä¸ªçº¿ç¨ä¸åçé¶æ®µï¼ï¼æ¬è´¨ä¸æµæ°´çº¿ææ¯å¹¶ä¸è½ç¼©çåæ¡æä»¤çæ§è¡æ¶é´ï¼ä½åç¸å°æé«äºæä»¤å°ååç
å¤çå¨å¨è¿è¡éæåºæ¶ï¼å¿
é¡»è¦èè**æä»¤ä¹é´çæ°æ®ä¾èµæ§**
* å线ç¨ç¯å¢ä¹å卿令éæï¼ç±äºåå¨ä¾èµæ§ï¼æç»æ§è¡ç»æå代ç 顺åºçç»æä¸è´
* å¤çº¿ç¨ç¯å¢ä¸çº¿ç¨äº¤æ¿æ§è¡ï¼ç±äºç¼è¯å¨ä¼åéæï¼ä¼è·åå
¶ä»çº¿ç¨å¤å¨ä¸åé¶æ®µçæä»¤åæ¶æ§è¡
è¡¥å
ç¥è¯ï¼
* æä»¤å¨ææ¯ååºä¸æ¡æä»¤å¹¶æ§è¡è¿æ¡æä»¤çæ¶é´ï¼ä¸è¬ç±è¥å¹²ä¸ªæºå¨å¨æç»æ
* æºå¨å¨æä¹ç§°ä¸º CPU 卿ï¼ä¸æ¡æä»¤çæ§è¡è¿ç¨åå为è¥å¹²ä¸ªé¶æ®µï¼å¦åæãè¯ç ãæ§è¡çï¼ï¼æ¯ä¸é¶æ®µå®æä¸ä¸ªåºæ¬æä½ï¼å®æä¸ä¸ªåºæ¬æä½æéè¦çæ¶é´ç§°ä¸ºæºå¨å¨æ
* æ¯è¡å¨ææå¨ææ§ä¿¡å·ä½å¨ææ§éå¤ååçæ¶é´é´é
***
### cache
#### ç¼åæºå¶
##### ç¼åç»æ
å¨è®¡ç®æºç³»ç»ä¸ï¼CPU é«éç¼åï¼CPU Cacheï¼ç®ç§°ç¼åï¼æ¯ç¨äºåå°å¤çå¨è®¿é®å
åæé平忶é´çé¨ä»¶ï¼å¨åå¨ä½ç³»ä¸ä½äºèªé¡¶åä¸ç第äºå±ï¼ä»
æ¬¡äº CPU å¯åå¨ï¼å
¶å®¹éè¿å°äºå
åï¼ä½é度å´å¯ä»¥æ¥è¿å¤çå¨çé¢ç
CPU å¤çå¨é度è¿è¿å¤§äºå¨ä¸»å
åä¸çï¼ä¸ºäºè§£å³é度差å¼ï¼å¨å®ä»¬ä¹é´æ¶è®¾äºå¤çº§ç¼åï¼å¦ L1ãL2ãL3 级å«çç¼åï¼è¿äºç¼å离 CPU è¶è¿å°±è¶å¿«ï¼å°é¢ç¹æä½çæ°æ®ç¼åå°è¿éï¼å 快访é®é度
| ä» CPU å° | 大约éè¦çæ¶é卿 |
| --------- | --------------------------------- |
| å¯åå¨ | 1 cycle (4GHz ç CPU 约为 0.25ns) |
| L1 | 3~4 cycle |
| L2 | 10~20 cycle |
| L3 | 40~45 cycle |
| å
å | 120~240 cycle |
##### ç¼å使ç¨
å½å¤çå¨ååºå
å访é®è¯·æ±æ¶ï¼ä¼å
æ¥çç¼åå
æ¯å¦æè¯·æ±æ°æ®ï¼å¦æåå¨ï¼å½ä¸ï¼ï¼åä¸ç¨è®¿é®å
åç´æ¥è¿åè¯¥æ°æ®ï¼å¦æä¸åå¨ï¼å¤±æï¼ï¼åè¦å
æå
åä¸çç¸åºæ°æ®è½½å
¥ç¼åï¼åå°å
¶è¿åå¤çå¨
ç¼å乿以ææï¼ä¸»è¦å 为ç¨åºè¿è¡æ¶å¯¹å
åç访é®åç°å±é¨æ§ï¼Localityï¼ç¹å¾ãæ¢å
æ¬ç©ºé´å±é¨æ§ï¼Spatial Localityï¼ï¼ä¹å
æ¬æ¶é´å±é¨æ§ï¼Temporal Localityï¼ï¼ææå©ç¨è¿ç§å±é¨æ§ï¼ç¼åå¯ä»¥è¾¾å°æé«çå½ä¸ç
***
#### 伪å
񄧮
**ç¼å以ç¼åè¡ cache line 为åä½**ï¼æ¯ä¸ªç¼åè¡å¯¹åºçä¸åå
åï¼ä¸è¬æ¯ 64 byteï¼8 个 longï¼ï¼å¨ CPU ä»ä¸»åè·åæ°æ®æ¶ï¼ä»¥ cache line 为åä½å è½½ï¼äºæ¯ç¸é»çæ°æ®ä¼ä¸å¹¶å è½½å°ç¼åä¸
ç¼åä¼é ææ°æ®å¯æ¬ç产çï¼å³åä¸ä»½æ°æ®ä¼ç¼åå¨ä¸åæ ¸å¿çç¼åè¡ä¸ï¼CPU è¦ä¿è¯æ°æ®çä¸è´æ§ï¼éè¦åå°æä¸ª CPU æ ¸å¿æ´æ¹äºæ°æ®ï¼å
¶å® CPU æ ¸å¿å¯¹åºç**æ´ä¸ªç¼åè¡å¿
须失æ**ï¼è¿å°±æ¯ä¼ªå
񄧮
è§£å³æ¹æ³ï¼
* paddingï¼éè¿å¡«å
ï¼è®©æ°æ®è½å¨ä¸åç cache line ä¸
* @Contendedï¼åçåè æ é â Adder â ä¼åæºå¶ â 伪å
񄧮
Linux æ¥ç CPU ç¼åè¡ï¼
* å½ä»¤ï¼`cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size64`
* å
åå°åæ ¼å¼ï¼[é«ä½ç»æ è®°] [ä½ä½ç´¢å¼] [åç§»é]
***
#### ç¼åä¸è´
ç¼åä¸è´æ§ï¼å½å¤ä¸ªå¤çå¨è¿ç®ä»»å¡é½æ¶åå°åä¸å主å
ååºåçæ¶åï¼å°å¯è½å¯¼è´åèªçç¼åæ°æ®ä¸ä¸æ ·
MESIï¼Modified Exclusive Shared Or Invalidï¼æ¯ä¸ç§å¹¿æ³ä½¿ç¨ç**æ¯æååçç¥çç¼åä¸è´æ§åè®®**ï¼CPU 䏿¯ä¸ªç¼åè¡ï¼caceh lineï¼ä½¿ç¨ 4 ç§ç¶æè¿è¡æ è®°ï¼ä½¿ç¨é¢å¤çä¸¤ä½ bit 表示)ï¼
* Mï¼è¢«ä¿®æ¹ï¼Modifiedï¼
该ç¼åè¡åªè¢«ç¼åå¨è¯¥ CPU çç¼åä¸ï¼å¹¶ä¸æ¯è¢«ä¿®æ¹è¿çï¼ä¸ä¸»åä¸çæ°æ®ä¸ä¸è´ (dirty)ï¼è¯¥ç¼åè¡ä¸çå
åéè¦å¨æªæ¥çæä¸ªæ¶é´ç¹ï¼å
¶å® CPU 读å主åä¸ç¸åºæ°æ®ä¹åï¼åå (write back) 主å
å½è¢«åå主åä¹åï¼è¯¥ç¼åè¡çç¶æä¼åæç¬äº« (exclusive) ç¶æã
* Eï¼ç¬äº«çï¼Exclusiveï¼
该ç¼åè¡åªè¢«ç¼åå¨è¯¥ CPU çç¼åä¸ï¼æ¯æªè¢«ä¿®æ¹è¿ç (clear)ï¼ä¸ä¸»å䏿°æ®ä¸è´ï¼è¯¥ç¶æå¯ä»¥å¨ä»»ä½æ¶å»æå
¶å® CPU 读å该å
åæ¶åæå
±äº«ç¶æ (shared)
å½ CPU ä¿®æ¹è¯¥ç¼åè¡ä¸å
容æ¶ï¼è¯¥ç¶æå¯ä»¥åæ Modified ç¶æ
* Sï¼å
±äº«çï¼Sharedï¼
è¯¥ç¶ææå³ç该ç¼åè¡å¯è½è¢«å¤ä¸ª CPU ç¼åï¼å¹¶ä¸å个ç¼åä¸çæ°æ®ä¸ä¸»åæ°æ®ä¸è´ï¼å½æä¸ä¸ª CPU ä¿®æ¹è¯¥ç¼åè¡ä¸ï¼å
¶å® CPU ä¸è¯¥ç¼åè¡åææ æç¶æ (Invalid)
* Iï¼æ æçï¼Invalidï¼
该ç¼åæ¯æ æçï¼å¯è½æå
¶å® CPU ä¿®æ¹äºè¯¥ç¼åè¡
è§£å³æ¹æ³ï¼å个å¤çå¨è®¿é®ç¼åæ¶é½éµå¾ªä¸äºåè®®ï¼å¨è¯»åæ¶è¦æ ¹æ®åè®®è¿è¡æä½ï¼åè®®ä¸»è¦æ MSIãMESI ç
****
#### å¤çæºå¶
åæ ¸ CPU å¤çå¨ä¼èªå¨ä¿è¯åºæ¬å
åæä½çååæ§
夿 ¸ CPU å¤çå¨ï¼æ¯ä¸ª CPU å¤çå¨å
ç»´æ¤äºä¸åå
åï¼æ¯ä¸ªå
æ ¸å
é¨ç»´æ¤çä¸åç¼åï¼å½å¤çº¿ç¨å¹¶åè¯»åæ¶ï¼å°±ä¼åºç°ç¼åæ°æ®ä¸ä¸è´çæ
åµãå¤ç卿ä¾ï¼
* æ»çº¿éå®ï¼å½å¤çå¨è¦æä½å
±äº«åéæ¶ï¼å¨ BUS æ»çº¿ä¸ååºä¸ä¸ª LOCK ä¿¡å·ï¼å
¶ä»å¤çå¨å°±æ æ³æä½è¿ä¸ªå
±äº«åéï¼è¯¥æä½ä¼å¯¼è´å¤§éé»å¡ï¼ä»èå¢å ç³»ç»çæ§è½å¼éï¼**å¹³å°çº§å«çå é**ï¼
* ç¼åéå®ï¼å½å¤çå¨å¯¹ç¼åä¸çå
±äº«åéè¿è¡äºæä½ï¼å
¶ä»å¤ç卿å
æ¢æºå¶ï¼å°åèªç¼åä¸ç该å
±äº«åéç失æï¼è¯»åæ¶ä¼éæ°ä»ä¸»å
åä¸è¯»åææ°çæ°æ®ï¼åºäº MESI ç¼åä¸è´æ§åè®®æ¥å®ç°
æå¦ä¸ä¸¤ç§æ
åµå¤çå¨ä¸ä¼ä½¿ç¨ç¼åéå®ï¼
* 彿ä½çæ°æ®è·¨å¤ä¸ªç¼åè¡ï¼ææ²¡è¢«ç¼åå¨å¤çå¨å
é¨ï¼åå¤çå¨ä¼ä½¿ç¨æ»çº¿éå®
* æäºå¤çå¨ä¸æ¯æç¼åéå®ï¼æ¯å¦ï¼Intel 486 å Pentium å¤çå¨ä¹ä¼è°ç¨æ»çº¿éå®
æ»çº¿æºå¶ï¼
* æ»çº¿å
æ¢ï¼æ¯ä¸ªå¤çå¨éè¿å
æ¢å¨æ»çº¿ä¸ä¼ æçæ°æ®æ¥æ£æ¥èªå·±ç¼å弿¯å¦è¿æäºï¼å½å¤çå¨åç°èªå·±çç¼å对åºçå
åå°åçæ°æ®è¢«ä¿®æ¹ï¼å°±**å°å½åå¤çå¨çç¼åè¡è®¾ç½®ä¸ºæ æç¶æ**ï¼å½å¤çå¨å¯¹è¿ä¸ªæ°æ®è¿è¡æä½æ¶ï¼ä¼éæ°ä»å
åä¸ææ°æ®è¯»åå°å¤çå¨ç¼åä¸
* æ»çº¿é£æ´ï¼ç±äº volatile ç MESI ç¼åä¸è´æ§åè®®ï¼éè¦ä¸æçä»ä¸»å
åå
æ¢å CAS 循ç¯ï¼æ æç交äºä¼å¯¼è´æ»çº¿å¸¦å®½è¾¾å°å³°å¼ï¼å æ¤ä¸è¦å¤§éä½¿ç¨ volatile å
³é®åï¼ä½¿ç¨ volatileãsyschonized é½éè¦æ ¹æ®å®é
åºæ¯
***
### volatile
#### 忥æºå¶
volatile æ¯ Java èææºæä¾ç**è½»é级**ç忥æºå¶ï¼ä¸å¤§ç¹æ§ï¼
- ä¿è¯å¯è§æ§
- ä¸ä¿è¯ååæ§
- ä¿è¯æåºæ§ï¼ç¦æ¢æä»¤éæï¼
æ§è½ï¼volatile 修饰çåéè¿è¡è¯»æä½ä¸æ®éåéå 乿²¡ä»ä¹å·®å«ï¼ä½æ¯åæä½ç¸å¯¹æ
¢ä¸äºï¼å 为éè¦å¨æ¬å°ä»£ç 䏿å
¥å¾å¤å
åå±éæ¥ä¿è¯æä»¤ä¸ä¼åçä¹±åºæ§è¡ï¼ä½æ¯å¼éæ¯éè¦å°
synchronized æ æ³ç¦æ¢æä»¤éæåå¤çå¨ä¼åï¼ä¸ºä»ä¹å¯ä»¥ä¿è¯æåºæ§å¯è§æ§
* å äºéä¹åï¼åªè½æä¸ä¸ªçº¿ç¨è·å¾å°äºéï¼è·å¾ä¸å°éç线ç¨å°±è¦é»å¡ï¼æä»¥å䏿¶é´åªæä¸ä¸ªçº¿ç¨æ§è¡ï¼ç¸å½äºå线ç¨ï¼ç±äºæ°æ®ä¾èµæ§çåå¨ï¼å线ç¨çæä»¤éææ¯æ²¡æé®é¢ç
* 线ç¨å éåï¼å°**æ¸
空工ä½å
å**ä¸å
±äº«åéçå¼ï¼ä½¿ç¨å
±äº«åéæ¶éè¦ä»ä¸»å
åä¸éæ°è¯»åææ°çå¼ï¼çº¿ç¨è§£éåï¼å¿
é¡»æå
±äº«åéçææ°å¼**å·æ°å°ä¸»å
å**ä¸ï¼JMM å
å交äºç« èæè®²ï¼
***
#### æä»¤éæ
volatile 修饰çåéï¼å¯ä»¥ç¦ç¨æä»¤éæ
æä»¤éæå®ä¾ï¼
* example 1ï¼
```java
public void mySort() {
int x = 11; //è¯å¥1
int y = 12; //è¯å¥2 è°å
æ§è¡ææä¸æ ·
x = x + 5; //è¯å¥3
y = x * x; //è¯å¥4
}
```
æ§è¡é¡ºåºæ¯ï¼1 2 3 4ã2 1 3 4ã1 3 2 4
æä»¤éæä¹æéå¶ä¸ä¼åºç°ï¼4321ï¼è¯å¥ 4 éè¦ä¾èµäº y 以å x çç³æï¼å 为å卿°æ®ä¾èµï¼æ æ³é¦å
æ§è¡
* example 2ï¼
```java
int num = 0;
boolean ready = false;
// 线ç¨1 æ§è¡æ¤æ¹æ³
public void actor1(I_Result r) {
if(ready) {
r.r1 = num + num;
} else {
r.r1 = 1;
}
}
// 线ç¨2 æ§è¡æ¤æ¹æ³
public void actor2(I_Result r) {
num = 2;
ready = true;
}
```
æ
åµä¸ï¼çº¿ç¨ 1 å
æ§è¡ï¼ready = falseï¼ç»æä¸º r.r1 = 1
æ
åµäºï¼çº¿ç¨ 2 å
æ§è¡ num = 2ï¼ä½è¿æ²¡æ§è¡ ready = trueï¼çº¿ç¨ 1 æ§è¡ï¼ç»æä¸º r.r1 = 1
æ
åµä¸ï¼çº¿ç¨ 2 å
æ§è¡ ready = trueï¼çº¿ç¨ 1 æ§è¡ï¼è¿å
¥ if åæ¯ç»æä¸º r.r1 = 4
æ
åµåï¼çº¿ç¨ 2 æ§è¡ ready = trueï¼åæ¢å°çº¿ç¨ 1ï¼è¿å
¥ if åæ¯ä¸º r.r1 = 0ï¼åååçº¿ç¨ 2 æ§è¡ num = 2ï¼åçæä»¤éæ
****
#### åºå±åç
##### ç¼åä¸è´
ä½¿ç¨ volatile 修饰çå
±äº«åéï¼æ»çº¿ä¼å¼å¯ **CPU æ»çº¿å
æ¢æºå¶**æ¥è§£å³ JMM ç¼åä¸è´æ§é®é¢ï¼ä¹å°±æ¯å
±äº«åéå¨å¤çº¿ç¨ä¸å¯è§æ§çé®é¢ï¼å®ç° MESI ç¼åä¸è´æ§åè®®
åºå±æ¯éè¿æ±ç¼ lock åç¼æä»¤ï¼å
±äº«åéå äº lock åç¼æä»¤å°±ä¼è¿è¡ç¼åéå®ï¼å¨çº¿ç¨ä¿®æ¹å®å
±äº«åéååå主åï¼å
¶ä»ç CPU æ ¸å¿ä¸è¿è¡ççº¿ç¨æ ¹æ®æ»çº¿å
æ¢æºå¶ä¼ä¿®æ¹å
¶å
±äº«åé为失æç¶æï¼è¯»åæ¶ä¼éæ°ä»ä¸»å
åä¸è¯»åææ°çæ°æ®
lock åç¼æä»¤å°±ç¸å½äºå
åå±éï¼Memory Barrierï¼Memory Fenceï¼
* 对 volatile åéçåæä»¤åä¼å å
¥åå±é
* 对 volatile åéç读æä»¤åä¼å å
¥è¯»å±é
å
åå±éæä¸ä¸ªä½ç¨ï¼
- ç¡®ä¿å¯¹å
åç读-æ¹-åæä½ååæ§è¡
- 黿¢å±é两侧çæä»¤éæåº
- å¼ºå¶æç¼åä¸çèæ°æ®åå主å
åï¼è®©ç¼åè¡ä¸ç¸åºçæ°æ®å¤±æ
***
##### å
åå±é
ä¿è¯**å¯è§æ§**ï¼
* åå±éï¼sfenceï¼Store Barrierï¼ä¿è¯å¨è¯¥å±éä¹åçï¼å¯¹å
±äº«åéçæ¹å¨ï¼é½åæ¥å°ä¸»åå½ä¸
```java
public void actor2(I_Result r) {
num = 2;
ready = true; // ready æ¯ volatile èµå¼å¸¦åå±é
// åå±é
}
```
* 读å±éï¼lfenceï¼Load Barrierï¼ä¿è¯å¨è¯¥å±éä¹åçï¼å¯¹å
±äº«åéç读åï¼ä»ä¸»åå·æ°åéå¼ï¼å è½½çæ¯ä¸»åä¸ææ°æ°æ®
```java
public void actor1(I_Result r) {
// 读å±é
// ready æ¯ volatile 读åå¼å¸¦è¯»å±é
if(ready) {
r.r1 = num + num;
} else {
r.r1 = 1;
}
}
```
* å
¨è½å±éï¼mfenceï¼modify/mix Barrierï¼ï¼å
¼å
· sfence å lfence çåè½
ä¿è¯**æåºæ§**ï¼
* åå±éä¼ç¡®ä¿æä»¤éæåºæ¶ï¼ä¸ä¼å°åå±éä¹åçä»£ç æå¨åå±éä¹å
* 读å±éä¼ç¡®ä¿æä»¤éæåºæ¶ï¼ä¸ä¼å°è¯»å±éä¹åçä»£ç æå¨è¯»å±éä¹å
ä¸è½è§£å³æä»¤äº¤éï¼
* åå±éä»
ä»
æ¯ä¿è¯ä¹åç读è½å¤è¯»å°ææ°çç»æï¼ä½ä¸è½ä¿è¯å
¶ä»çº¿ç¨ç读è·å°åå±éä¹å
* æåºæ§çä¿è¯ä¹åªæ¯ä¿è¯äºæ¬çº¿ç¨å
ç¸å
³ä»£ç ä¸è¢«éæåº
```java
volatile i = 0;
new Thread(() -> {i++});
new Thread(() -> {i--});
```
i++ åç¼è¯åçæä»¤ï¼
```java
0: iconst_1 // å½intåå¼ -1~5 æ¶ï¼JVMéç¨iconstæä»¤å°å¸¸éåå
¥æ ä¸
1: istore_1 // 尿使°æ é¡¶æ°æ®å¼¹åºï¼åå
¥å±é¨åé表ç slot 1
2: iinc 1, 1
```
****
##### 交äºè§å
å¯¹äº volatile 修饰çåéï¼
* 线ç¨å¯¹åéç use ä¸ loadãread æä½æ¯ç¸å
³èçï¼æä»¥åé使ç¨åå¿
é¡»å
ä»ä¸»åå è½½
* 线ç¨å¯¹åéç assign ä¸ storeãwrite æä½æ¯ç¸å
³èçï¼æä»¥åé使ç¨åå¿
须忥è³ä¸»å
* çº¿ç¨ 1 åçº¿ç¨ 2 è°å
对åéæ§è¡ read æä½ï¼å°±ä¼å
è¿è¡ write æä½ï¼é²æ¢æä»¤éæ
***
#### å端æ£é
##### æ£éæºå¶
Double-Checked Lockingï¼å端æ£éæºå¶
DCLï¼å端æ£éï¼æºå¶ä¸ä¸å®æ¯çº¿ç¨å®å
¨çï¼åå æ¯ææä»¤éæçåå¨ï¼å å
¥ volatile å¯ä»¥ç¦æ¢æä»¤éæ
```java
public final class Singleton {
private Singleton() { }
private static Singleton INSTANCE = null;
public static Singleton getInstance() {
if(INSTANCE == null) { // t2ï¼è¿éç夿䏿¯çº¿ç¨å®å
¨ç
// 馿¬¡è®¿é®ä¼åæ¥ï¼èä¹åçä½¿ç¨æ²¡æ synchronized
synchronized(Singleton.class) {
// è¿éæ¯çº¿ç¨å®å
¨ç夿ï¼é²æ¢å
¶ä»çº¿ç¨å¨å½å线ç¨çå¾
éçæé´å®æäºåå§å
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
```
ä¸é INSTANCE çåå ï¼
* INSTANCE è¦éæ°èµå¼
* INSTANCE æ¯ nullï¼çº¿ç¨å éä¹åéè¦è·å对象çå¼ç¨ï¼è®¾ç½®å¯¹è±¡å¤´ï¼null 没æå¼ç¨
å®ç°ç¹ç¹ï¼
* ææ°åå§å
* 馿¬¡ä½¿ç¨ getInstance() æä½¿ç¨ synchronized å éï¼åç»ä½¿ç¨æ¶æ éå é
* 第ä¸ä¸ª if 使ç¨äº INSTANCE åéï¼æ¯å¨åæ¥åä¹å¤ï¼ä½å¨å¤çº¿ç¨ç¯å¢ä¸ä¼äº§çé®é¢
***
##### DCLé®é¢
getInstance æ¹æ³å¯¹åºçåèç 为ï¼
```java
0: getstatic #2 // Field INSTANCE:Ltest/Singleton;
3: ifnonnull 37
6: ldc #3 // class test/Singleton
8: dup
9: astore_0
10: monitorenter
11: getstatic #2 // Field INSTANCE:Ltest/Singleton;
14: ifnonnull 27
17: new #3 // class test/Singleton
20: dup
21: invokespecial #4 // Method "":()V
24: putstatic #2 // Field INSTANCE:Ltest/Singleton;
27: aload_0
28: monitorexit
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #2 // Field INSTANCE:Ltest/Singleton;
40: areturn
```
* 17 表示å建对象ï¼å°å¯¹è±¡å¼ç¨å
¥æ
* 20 表示å¤å¶ä¸ä»½å¯¹è±¡å¼ç¨ï¼å¼ç¨å°å
* 21 表示å©ç¨ä¸ä¸ªå¯¹è±¡å¼ç¨ï¼è°ç¨æé æ¹æ³åå§å对象
* 24 表示å©ç¨ä¸ä¸ªå¯¹è±¡å¼ç¨ï¼èµå¼ç» static INSTANCE
**æ¥éª¤ 21 å 24 ä¹é´ä¸å卿°æ®ä¾èµå
³ç³»**ï¼è䏿 论éæååï¼ç¨åºçæ§è¡ç»æå¨å线ç¨ä¸å¹¶æ²¡ææ¹åï¼å æ¤è¿ç§éæä¼åæ¯å
许ç
* å
³é®å¨äº 0:getstatic è¿è¡ä»£ç å¨ monitor æ§å¶ä¹å¤ï¼å¯ä»¥è¶è¿ monitor 读å INSTANCE åéçå¼
* å½å
¶ä»çº¿ç¨è®¿é® INSTANCE ä¸ä¸º null æ¶ï¼ç±äº INSTANCE å®ä¾æªå¿
å·²åå§åï¼é£ä¹ t2 æ¿å°çæ¯å°æ¯ä¸ä¸ªæªåå§å宿¯çåä¾è¿åï¼è¿å°±é æäºçº¿ç¨å®å
¨çé®é¢

***
##### è§£å³æ¹æ³
æä»¤éæåªä¼ä¿è¯ä¸²è¡è¯ä¹çæ§è¡ä¸è´æ§ï¼å线ç¨ï¼ï¼ä½å¹¶ä¸ä¼å
³ç³»å¤çº¿ç¨é´çè¯ä¹ä¸è´æ§
å¼å
¥ volatileï¼æ¥ä¿è¯åºç°æä»¤éæçé®é¢ï¼ä»èä¿è¯å便¨¡å¼ç线ç¨å®å
¨æ§ï¼
```java
private static volatile SingletonDemo INSTANCE = null;
```
***
### ha-be
happens-before å
è¡åç
Java å
忍¡åå
·å¤ä¸äºå
天çâæåºæ§âï¼å³ä¸éè¦éè¿ä»»ä½åæ¥ææ®µï¼volatileãsynchronized çï¼å°±è½å¤å¾å°ä¿è¯çå®å
¨ï¼è¿ä¸ªé常ä¹ç§°ä¸º happens-before ååï¼å®æ¯å¯è§æ§ä¸æåºæ§çä¸å¥è§åæ»ç»
ä¸ç¬¦å happens-before è§åï¼JMM å¹¶ä¸è½ä¿è¯ä¸ä¸ªçº¿ç¨çå¯è§æ§åæåºæ§
1. ç¨åºæ¬¡åºè§å (Program Order Rule)ï¼ä¸ä¸ªçº¿ç¨å
ï¼é»è¾ä¸ä¹¦åå¨åé¢çæä½å
è¡åçäºä¹¦åå¨åé¢çæä½ ï¼å 为å¤ä¸ªæä½ä¹é´æå
åä¾èµå
³ç³»ï¼åä¸å
许对è¿äºæä½è¿è¡éæåº
2. éå®è§å (Monitor Lock Rule)ï¼ä¸ä¸ª unlock æä½å
è¡åçäºåé¢ï¼æ¶é´çå
åï¼å¯¹åä¸ä¸ªéç lock æä½ï¼æä»¥çº¿ç¨è§£é m ä¹å对åéçåï¼è§£éåä¼å·æ°å°ä¸»å
åä¸ï¼ï¼å¯¹äºæ¥ä¸æ¥å¯¹ m å éçå
¶å®çº¿ç¨å¯¹è¯¥åéç读å¯è§
3. **volatile åéè§å** (Volatile Variable Rule)ï¼å¯¹ volatile åéçåæä½å
è¡åçäºåé¢å¯¹è¿ä¸ªåéç读
4. ä¼ éè§å (Transitivity)ï¼å
·æä¼ éæ§ï¼å¦ææä½ A å
è¡åçäºæä½ Bï¼èæä½ B åå
è¡åçäºæä½ Cï¼åå¯ä»¥å¾åºæä½ A å
è¡åçäºæä½ C
5. 线ç¨å¯å¨è§å (Thread Start Rule)ï¼Thread 对象ç start()æ¹ æ³å
è¡åçäºæ¤çº¿ç¨ä¸çæ¯ä¸ä¸ªæä½
```java
static int x = 10;//çº¿ç¨ start å对åéçåï¼å¯¹è¯¥çº¿ç¨å¼å§å对该åéç读å¯è§
new Thread(()->{ System.out.println(x); },"t1").start();
```
6. 线ç¨ä¸æè§å (Thread Interruption Rule)ï¼å¯¹çº¿ç¨ interrupt() æ¹æ³çè°ç¨å
è¡åçäºè¢«ä¸æçº¿ç¨çä»£ç æ£æµå°ä¸æäºä»¶çåç
7. 线ç¨ç»æ¢è§å (Thread Termination Rule)ï¼çº¿ç¨ä¸ææçæä½é½å
è¡åçäºçº¿ç¨çç»æ¢æ£æµï¼å¯ä»¥éè¿ Thread.join() æ¹æ³ç»æãThread.isAlive() çè¿åå¼ææ®µæ£æµå°çº¿ç¨å·²ç»ç»æ¢æ§è¡
8. 对象ç»ç»è§åï¼Finaizer Ruleï¼ï¼ä¸ä¸ªå¯¹è±¡çåå§åå®æï¼æé 彿°æ§è¡ç»æï¼å
è¡åçäºå®ç finalize() æ¹æ³çå¼å§
***
### 设计模å¼
#### ç»æ¢æ¨¡å¼
ç»æ¢æ¨¡å¼ä¹ä¸¤é¶æ®µç»æ¢æ¨¡å¼ï¼åæ¢æ è®°ç¨ volatile æ¯ä¸ºäºä¿è¯è¯¥åéå¨å¤ä¸ªçº¿ç¨ä¹é´çå¯è§æ§
```java
class TwoPhaseTermination {
// çæ§çº¿ç¨
private Thread monitor;
// 忢æ è®°
private volatile boolean stop = false;;
// å¯å¨çæ§çº¿ç¨
public void start() {
monitor = new Thread(() -> {
while (true) {
Thread thread = Thread.currentThread();
if (stop) {
System.out.println("åç½®å¤ç");
break;
}
try {
Thread.sleep(1000);// ç¡ç
System.out.println(thread.getName() + "æ§è¡çæ§è®°å½");
} catch (InterruptedException e) {
System.out.println("被ææï¼éåºç¡ç ");
}
}
});
monitor.start();
}
// åæ¢çæ§çº¿ç¨
public void stop() {
stop = true;
monitor.interrupt();// 让线ç¨å°½å¿«éåºTimed Waiting
}
}
// æµè¯
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination tpt = new TwoPhaseTermination();
tpt.start();
Thread.sleep(3500);
System.out.println("åæ¢çæ§");
tpt.stop();
}
```
****
#### Balking
Balking ï¼ç¹è±«ï¼æ¨¡å¼ç¨å¨ä¸ä¸ªçº¿ç¨åç°å¦ä¸ä¸ªçº¿ç¨ææ¬çº¿ç¨å·²ç»åäºæä¸ä»¶ç¸åçäºï¼é£ä¹æ¬çº¿ç¨å°±æ éååäºï¼ç´æ¥ç»æè¿å
```java
public class MonitorService {
// ç¨æ¥è¡¨ç¤ºæ¯å¦å·²ç»æçº¿ç¨å·²ç»å¨æ§è¡å¯å¨äº
private volatile boolean starting = false;
public void start() {
System.out.println("å°è¯å¯å¨çæ§çº¿ç¨...");
synchronized (this) {
if (starting) {
return;
}
starting = true;
}
// çæ£å¯å¨çæ§çº¿ç¨...
}
}
```
对æ¯ä¿æ¤æ§æå模å¼ï¼ä¿æ¤æ§æå模å¼ç¨å¨ä¸ä¸ªçº¿ç¨çå¾
å¦ä¸ä¸ªçº¿ç¨çæ§è¡ç»æï¼å½æ¡ä»¶ä¸æ»¡è¶³æ¶çº¿ç¨çå¾
ä¾åï¼å¸æ doInit() æ¹æ³ä»
被è°ç¨ä¸æ¬¡ï¼ä¸é¢çå®ç°åºç°çé®é¢ï¼
* å½ t1 线ç¨è¿å
¥ init() åå¤ doInit()ï¼t2 线ç¨è¿æ¥ï¼initialized è¿ä¸ºf alseï¼å t2 å°±ååå§å䏿¬¡
* volatile éåä¸ä¸ªçº¿ç¨åï¼å
¶ä»çº¿ç¨è¯»çæ
åµï¼è¿ä¸ªä»£ç éè¦å é
```java
public class TestVolatile {
volatile boolean initialized = false;
void init() {
if (initialized) {
return;
}
doInit();
initialized = true;
}
private void doInit() {
}
}
```
****
## æ é
### CAS
#### åç
æ éç¼ç¨ï¼Lock Free
CAS çå
¨ç§°æ¯ Compare-And-Swapï¼æ¯ **CPU å¹¶ååè¯**
* CAS å¹¶ååè¯ä½ç°å¨ Java è¯è¨ä¸å°±æ¯ sun.misc.Unsafe ç±»çåä¸ªæ¹æ³ï¼è°ç¨ UnSafe ç±»ä¸ç CAS æ¹æ³ï¼JVM ä¼å®ç°åº CAS æ±ç¼æä»¤ï¼è¿æ¯ä¸ç§å®å
¨ä¾èµäºç¡¬ä»¶çåè½ï¼å®ç°äºååæä½
* CAS æ¯ä¸ç§ç³»ç»åè¯ï¼åè¯å±äºæä½ç³»ç»èç´ï¼æ¯ç±è¥å¹²æ¡æä»¤ç»æ ï¼ç¨äºå®ææä¸ªåè½çä¸ä¸ªè¿ç¨ï¼å¹¶ä¸åè¯çæ§è¡å¿
é¡»æ¯è¿ç»çï¼æ§è¡è¿ç¨ä¸ä¸å
è®¸è¢«ä¸æï¼æä»¥ CAS æ¯ä¸æ¡ CPU çååæä»¤ï¼ä¸ä¼é ææ°æ®ä¸ä¸è´çé®é¢ï¼æ¯çº¿ç¨å®å
¨ç
åºå±åçï¼CAS çåºå±æ¯ `lock cmpxchg` æä»¤ï¼X86 æ¶æï¼ï¼å¨åæ ¸å夿 ¸ CPU ä¸é½è½å¤ä¿è¯æ¯è¾äº¤æ¢çååæ§
* ç¨åºæ¯å¨åæ ¸å¤çå¨ä¸è¿è¡ï¼ä¼çç¥ lock åç¼ï¼åå¤çå¨èªèº«ä¼ç»´æ¤å¤çå¨å
ç顺åºä¸è´æ§ï¼ä¸éè¦ lock åç¼çå
åå±éææ
* ç¨åºæ¯å¨å¤æ ¸å¤çå¨ä¸è¿è¡ï¼ä¼ä¸º cmpxchg æä»¤å ä¸ lock åç¼ãå½æä¸ªæ ¸æ§è¡å°å¸¦ lock çæä»¤æ¶ï¼CPU 伿§è¡**æ»çº¿é宿ç¼åéå®**ï¼å°ä¿®æ¹çåéåå
¥å°ä¸»åï¼è¿ä¸ªè¿ç¨ä¸ä¼è¢«çº¿ç¨çè°åº¦æºå¶æææï¼ä¿è¯äºå¤ä¸ªçº¿ç¨å¯¹å
åæä½çååæ§
ä½ç¨ï¼æ¯è¾å½åå·¥ä½å
åä¸çå¼å主ç©çå
åä¸çå¼ï¼å¦æç¸ååæ§è¡è§å®æä½ï¼å¦åç»§ç»æ¯è¾ç´å°ä¸»å
ååå·¥ä½å
åçå¼ä¸è´ä¸ºæ¢
CAS ç¹ç¹ï¼
* CAS ä½ç°çæ¯**æ éå¹¶åãæ é»å¡å¹¶å**ï¼çº¿ç¨ä¸ä¼é·å
¥é»å¡ï¼çº¿ç¨ä¸éè¦é¢ç¹åæ¢ç¶æï¼ä¸ä¸æåæ¢ï¼ç³»ç»è°ç¨ï¼
* CAS æ¯åºäºä¹è§éçææ³
CAS 缺ç¹ï¼
- å¾ªç¯æ¶é´é¿ï¼å¼é大ï¼å 为æ§è¡çæ¯å¾ªç¯æä½ï¼å¦ææ¯è¾ä¸æåä¸ç´å¨å¾ªç¯ï¼æå·®çæ
åµæä¸ªçº¿ç¨ä¸ç´åå°çå¼å颿å¼é½ä¸ä¸æ ·ï¼å°±ä¼æ é循ç¯å¯¼è´é¥¥é¥¿ï¼**ä½¿ç¨ CAS çº¿ç¨æ°ä¸è¦è¶
è¿ CPU çæ ¸å¿æ°**
- åªè½ä¿è¯ä¸ä¸ªå
±äº«åéçååæä½
- 对äºä¸ä¸ªå
±äº«åéæ§è¡æä½æ¶ï¼å¯ä»¥éè¿å¾ªç¯ CAS çæ¹å¼æ¥ä¿è¯ååæä½
- 对äºå¤ä¸ªå
±äº«åéæä½æ¶ï¼å¾ªç¯ CAS å°±æ æ³ä¿è¯æä½çååæ§ï¼è¿ä¸ªæ¶å**åªè½ç¨éæ¥ä¿è¯ååæ§**
- å¼åºæ¥ ABA é®é¢
***
#### ä¹è§é
CAS ä¸ synchronized æ»ç»ï¼
* synchronized æ¯ä»æ²è§çè§åº¦åºåï¼æ»æ¯å设æåçæ
åµï¼æ¯æ¬¡å»æ¿æ°æ®çæ¶åé½è®¤ä¸ºå«äººä¼ä¿®æ¹ï¼æä»¥æ¯æ¬¡å¨æ¿æ°æ®çæ¶åé½ä¼ä¸éï¼è¿æ ·å«äººæ³æ¿è¿ä¸ªæ°æ®å°±ä¼é»å¡ï¼å
±äº«èµæºæ¯æ¬¡åªç»ä¸ä¸ªçº¿ç¨ä½¿ç¨ï¼å
¶å®çº¿ç¨é»å¡ï¼ç¨å®ååæèµæºè½¬è®©ç»å
¶å®çº¿ç¨ï¼ï¼å æ¤ synchronized ä¹ç§°ä¹ä¸ºæ²è§éï¼ReentrantLock 乿¯ä¸ç§æ²è§éï¼æ§è½è¾å·®
* CAS æ¯ä»ä¹è§çè§åº¦åºåï¼æ»æ¯å设æå¥½çæ
åµï¼æ¯æ¬¡å»æ¿æ°æ®çæ¶åé½è®¤ä¸ºå«äººä¸ä¼ä¿®æ¹ï¼æä»¥ä¸ä¼ä¸éï¼ä½æ¯å¨æ´æ°çæ¶åä¼å¤æä¸ä¸å¨æ¤æé´å«äººææ²¡æå»æ´æ°è¿ä¸ªæ°æ®ã**妿å«äººä¿®æ¹è¿ï¼åè·åç°å¨ææ°çå¼ï¼å¦æå«äººæ²¡ä¿®æ¹è¿ï¼ç´æ¥ä¿®æ¹å
±äº«æ°æ®çå¼**ï¼CAS è¿ç§æºå¶ä¹ç§°ä¹ä¸ºä¹è§éï¼ç»¼åæ§è½è¾å¥½
***
### Atomic
#### 常ç¨API
常è§ååç±»ï¼AtomicIntegerãAtomicBooleanãAtomicLong
æé æ¹æ³ï¼
* `public AtomicInteger()`ï¼åå§åä¸ä¸ªé»è®¤å¼ä¸º 0 çååå Integer
* `public AtomicInteger(int initialValue)`ï¼åå§åä¸ä¸ªæå®å¼çååå Integer
常ç¨APIï¼
| æ¹æ³ | ä½ç¨ |
| ------------------------------------- | ------------------------------------------------------------ |
| public final int get() | è·å AtomicInteger çå¼ |
| public final int getAndIncrement() | 以ååæ¹å¼å°å½åå¼å 1ï¼è¿åçæ¯èªå¢åçå¼ |
| public final int incrementAndGet() | 以ååæ¹å¼å°å½åå¼å 1ï¼è¿åçæ¯èªå¢åçå¼ |
| public final int getAndSet(int value) | 以ååæ¹å¼è®¾ç½®ä¸º newValue çå¼ï¼è¿åæ§å¼ |
| public final int addAndGet(int data) | 以ååæ¹å¼å°è¾å
¥çæ°å¼ä¸å®ä¾ä¸çå¼ç¸å å¹¶è¿å
å®ä¾ï¼AtomicInteger éç value |
***
#### åçåæ
**AtomicInteger åç**ï¼èªæé + CAS ç®æ³
CAS ç®æ³ï¼æ 3 个æä½æ°ï¼å
åå¼ Vï¼ æ§çé¢æå¼ Aï¼è¦ä¿®æ¹çå¼ Bï¼
* 彿§çé¢æå¼ A == å
åå¼ V æ¤æ¶å¯ä»¥ä¿®æ¹ï¼å° V æ¹ä¸º B
* 彿§çé¢æå¼ A != å
åå¼ V æ¤æ¶ä¸è½ä¿®æ¹ï¼å¹¶éæ°è·åç°å¨çææ°å¼ï¼éæ°è·åçå¨ä½å°±æ¯èªæ
åæ getAndSet æ¹æ³ï¼
* AtomicIntegerï¼
```java
public final int getAndSet(int newValue) {
/**
* this: å½å对象
* valueOffset: å
ååç§»éï¼å
åå°å
*/
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
```
valueOffsetï¼åç§»é表示该åéå¼ç¸å¯¹äºå½å对象å°åçåç§»ï¼Unsafe å°±æ¯æ ¹æ®å
ååç§»å°åè·åæ°æ®
```java
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
//è°ç¨æ¬å°æ¹æ³ -->
public native long objectFieldOffset(Field var1);
```
* unsafe ç±»ï¼
```java
// val1: AtomicInteger对象æ¬èº«ï¼var2: 该对象å¼å¾å¼ç¨å°åï¼var4: éè¦åå¨çæ°
public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
// var5: ç¨ var1 å var2 æ¾å°çå
åä¸ççå®å¼
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var4));
return var5;
}
```
var5ï¼ä»ä¸»å
å䏿·è´å°å·¥ä½å
åä¸çå¼ï¼æ¯æ¬¡é½è¦ä»ä¸»å
åæ¿å°ææ°çå¼å°æ¬å°å
åï¼ï¼ç¶åæ§è¡ `compareAndSwapInt()` åå主å
åçå¼è¿è¡æ¯è¾ï¼åè®¾æ¹æ³è¿å falseï¼é£ä¹å°±ä¸ç´æ§è¡ while æ¹æ³ï¼ç´å°ææçå¼åçå®å¼ä¸æ ·ï¼ä¿®æ¹æ°æ®
* åé value ç¨ volatile 修饰ï¼ä¿è¯äºå¤çº¿ç¨ä¹é´çå
åå¯è§æ§ï¼é¿å
线ç¨ä»å·¥ä½ç¼åä¸è·å失æçåé
```java
private volatile int value
```
**CAS å¿
é¡»åå© volatile æè½è¯»åå°å
±äº«åéçææ°å¼æ¥å®ç°æ¯è¾å¹¶äº¤æ¢çææ**
åæ getAndUpdate æ¹æ³ï¼
* getAndUpdateï¼
```java
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get(); //å½åå¼ï¼casçææå¼
next = updateFunction.applyAsInt(prev);//ææå¼æ´æ°å°è¯¥å¼
} while (!compareAndSet(prev, next));//èªæ
return prev;
}
```
彿°å¼æ¥å£ï¼å¯ä»¥èªå®ä¹æä½é»è¾
```java
AtomicInteger a = new AtomicInteger();
a.getAndUpdate(i -> i + 10);
```
* compareAndSetï¼
```java
public final boolean compareAndSet(int expect, int update) {
/**
* this: å½å对象
* valueOffset: å
ååç§»éï¼å
åå°å
* expect: ææçå¼
* update: æ´æ°çå¼
*/
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
```
***
#### ååå¼ç¨
ååå¼ç¨ï¼å¯¹ Object è¿è¡ååæä½ï¼æä¾ä¸ç§è¯»åå齿¯ååæ§ç对象å¼ç¨åé
ååå¼ç¨ç±»ï¼AtomicReferenceãAtomicStampedReferenceãAtomicMarkableReference
AtomicReference ç±»ï¼
* æé æ¹æ³ï¼`AtomicReference atomicReference = new AtomicReference()`
* å¸¸ç¨ APIï¼
* `public final boolean compareAndSet(V expectedValue, V newValue)`ï¼CAS æä½
* `public final void set(V newValue)`ï¼å°å¼è®¾ç½®ä¸º newValue
* `public final V get()`ï¼è¿åå½åå¼
```java
public class AtomicReferenceDemo {
public static void main(String[] args) {
Student s1 = new Student(33, "z3");
// å建ååå¼ç¨å
è£
ç±»
AtomicReference atomicReference = new AtomicReference<>();
// 设置主å
åå
±äº«åé为s1
atomicReference.set(s1);
// æ¯è¾å¹¶äº¤æ¢ï¼å¦æç°å¨ä¸»ç©çå
åçå¼ä¸º z3ï¼é£ä¹äº¤æ¢æ l4
while (true) {
Student s2 = new Student(44, "l4");
if (atomicReference.compareAndSet(s1, s2)) {
break;
}
}
System.out.println(atomicReference.get());
}
}
class Student {
private int id;
private String name;
//ãããã
}
```
***
#### ååæ°ç»
ååæ°ç»ç±»ï¼AtomicIntegerArrayãAtomicLongArrayãAtomicReferenceArray
AtomicIntegerArray ç±»æ¹æ³ï¼
```java
/**
* i the index
* expect the expected value
* update the new value
*/
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
```
***
#### ååæ´æ°å¨
ååæ´æ°å¨ç±»ï¼AtomicReferenceFieldUpdaterãAtomicIntegerFieldUpdaterãAtomicLongFieldUpdater
å©ç¨åæ®µæ´æ°å¨ï¼å¯ä»¥é对对象çæä¸ªåï¼Fieldï¼è¿è¡ååæä½ï¼åªè½é
å volatile 修饰çåæ®µä½¿ç¨ï¼å¦åä¼åºç°å¼å¸¸ `IllegalArgumentException: Must be volatile type`
å¸¸ç¨ APIï¼
* `static AtomicIntegerFieldUpdater newUpdater(Class c, String fieldName)`ï¼æé æ¹æ³
* `abstract boolean compareAndSet(T obj, int expect, int update)`ï¼CAS
```java
public class UpdateDemo {
private volatile int field;
public static void main(String[] args) {
AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater
.newUpdater(UpdateDemo.class, "field");
UpdateDemo updateDemo = new UpdateDemo();
fieldUpdater.compareAndSet(updateDemo, 0, 10);
System.out.println(updateDemo.field);//10
}
}
```
***
#### ååç´¯å å¨
ååç´¯å å¨ç±»ï¼LongAdderãDoubleAdderãLongAccumulatorãDoubleAccumulator
LongAdder å LongAccumulator åºå«ï¼
ç¸åç¹ï¼
* LongAddr ä¸ LongAccumulator ç±»é½æ¯ä½¿ç¨éé»å¡ç®æ³ CAS å®ç°ç
* LongAddr ç±»æ¯ LongAccumulator ç±»çä¸ä¸ªç¹ä¾ï¼åªæ¯ LongAccumulator æä¾äºæ´å¼ºå¤§çåè½ï¼å¯ä»¥èªå®ä¹ç´¯å è§åï¼å½accumulatorFunction 为 null æ¶å°±çä»·äº LongAddr
ä¸åç¹ï¼
* è°ç¨ casBase æ¶ï¼LongAccumulator ä½¿ç¨ function.applyAsLong(b = base, x) æ¥è®¡ç®ï¼LongAddr ä½¿ç¨ casBase(b = base, b + x)
* LongAccumulator ç±»åè½æ´å å¼ºå¤§ï¼æé æ¹æ³åæ°ä¸
* accumulatorFunction æ¯ä¸ä¸ªåç®è¿ç®å¨æ¥å£ï¼å¯ä»¥æå®ç´¯å è§åï¼æ¯å¦ç´¯å æè
ç¸ä¹ï¼å
¶æ ¹æ®è¾å
¥çä¸¤ä¸ªåæ°è¿åä¸ä¸ªè®¡ç®å¼ï¼LongAdder å
置累å è§å
* identity 忝 LongAccumulator ç´¯å å¨çåå§å¼ï¼LongAccumulator å¯ä»¥ä¸ºç´¯å 卿ä¾é0çåå§å¼ï¼è LongAdder åªè½æä¾é»è®¤ç 0
***
### Adder
#### ä¼åæºå¶
LongAdder æ¯ Java8 æä¾çç±»ï¼è· AtomicLong æç¸åçææï¼ä½å¯¹ CAS æºå¶è¿è¡äºä¼åï¼å°è¯ä½¿ç¨å段 CAS 以åèªå¨å段è¿ç§»çæ¹å¼æ¥å¤§å¹
度æåå¤çº¿ç¨é«å¹¶åæ§è¡ CAS æä½çæ§è½
CAS åºå±å®ç°æ¯å¨ä¸ä¸ªå¾ªç¯ä¸ä¸æå°å°è¯ä¿®æ¹ç®æ å¼ï¼ç´å°ä¿®æ¹æåã妿ç«äºä¸æ¿çä¿®æ¹æåçå¾é«ï¼å¦å失败çå¾é«ï¼å¤±è´¥åè¿äºéå¤çååæ§æä½ä¼èè´¹æ§è½ï¼å¯¼è´å¤§é线ç¨**空循ç¯ï¼èªæè½¬**ï¼
ä¼åæ ¸å¿ææ³ï¼æ°æ®å离ï¼å° AtomicLong ç**åç¹çæ´æ°åååæ
å°å个èç¹ï¼ç©ºé´æ¢æ¶é´**ï¼å¨ä½å¹¶åçæ¶åç´æ¥æ´æ°ï¼å¯ä»¥ä¿éå AtomicLong çæ§è½åºæ¬ä¸è´ï¼èå¨é«å¹¶åçæ¶åéè¿åæ£åå°ç«äºï¼æé«äºæ§è½
**åæ®µ CAS æºå¶**ï¼
* å¨åçç«äºæ¶ï¼å建 Cell æ°ç»ç¨äºå°ä¸å线ç¨çæä½ç¦»æ£ï¼éè¿ hash çç®æ³æ å°ï¼å°ä¸åçèç¹ä¸
* 设置å¤ä¸ªç´¯å åå
ï¼ä¼æ ¹æ®éè¦æ©å®¹ï¼æå¤§ä¸º CPU æ ¸æ°ï¼ï¼Therad-0 ç´¯å Cell[0]ï¼è Thread-1 ç´¯å Cell[1] çï¼æåå°ç»ææ±æ»
* å¨ç´¯å æ¶æä½çä¸åç Cell åéï¼å æ¤åå°äº CAS éè¯å¤±è´¥ï¼ä»èæé«æ§è½
**èªå¨å段è¿ç§»æºå¶**ï¼æä¸ª Cell ç value æ§è¡ CAS 失败ï¼å°±ä¼èªå¨å¯»æ¾å¦ä¸ä¸ª Cell åæ®µå
ç value å¼è¿è¡ CAS æä½
***
#### 伪å
񄧮
Cell 为累å åå
ï¼æ°ç»è®¿é®ç´¢å¼æ¯éè¿ Thread éç threadLocalRandomProbe å忍¡å®ç°çï¼è¿ä¸ªåæ¯ ThreadLocalRandom æ´æ°ç
```java
// Striped64.Cell
@sun.misc.Contended static final class Cell {
volatile long value;
Cell(long x) { value = x; }
// ç¨ cas æ¹å¼è¿è¡ç´¯å , prev 表示æ§å¼, next 表示æ°å¼
final boolean cas(long prev, long next) {
return UNSAFE.compareAndSwapLong(this, valueOffset, prev, next);
}
// çç¥ä¸éè¦ä»£ç
}
```
Cell æ¯æ°ç»å½¢å¼ï¼**å¨å
å䏿¯è¿ç»åå¨ç**ï¼64 ä½ç³»ç»ä¸ï¼ä¸ä¸ª Cell 为 24 åèï¼16 åèç对象头å 8 åèç valueï¼ï¼æ¯ä¸ä¸ª cache line 为 64 åèï¼å æ¤ç¼åè¡å¯ä»¥åä¸ 2 个ç Cell 对象ï¼å½ Core-0 è¦ä¿®æ¹ Cell[0]ãCore-1 è¦ä¿®æ¹ Cell[1]ï¼æ 论è°ä¿®æ¹æåé½ä¼å¯¼è´å½åç¼åè¡å¤±æï¼ä»è导è´å¯¹æ¹çæ°æ®å¤±æï¼éè¦éæ°å»ä¸»åè·åï¼å½±åæç

@sun.misc.Contendedï¼é²æ¢ç¼åè¡ä¼ªå
±äº«ï¼å¨ä½¿ç¨æ¤æ³¨è§£ç对象æå段çåååå¢å 128 åè大å°ç paddingï¼ä½¿ç¨ 2 åäºå¤§å¤æ°ç¡¬ä»¶ç¼åè¡è®© CPU å°å¯¹è±¡é¢è¯»è³ç¼åæ¶**å ç¨ä¸åçç¼åè¡**ï¼è¿æ ·å°±ä¸ä¼é æå¯¹æ¹ç¼åè¡ç失æ

***
#### æºç è§£æ
Striped64 ç±»æå屿§ï¼
```java
// 表示å½åè®¡ç®æºCPUæ°é
static final int NCPU = Runtime.getRuntime().availableProcessors()
// ç´¯å åå
æ°ç», ææ°åå§å
transient volatile Cell[] cells;
// åºç¡å¼, å¦ææ²¡æç«äº, åç¨ cas ç´¯å è¿ä¸ªåï¼å½ cells æ©å®¹æ¶ï¼ä¹ä¼å°æ°æ®åå° base ä¸
transient volatile long base;
// å¨ cells åå§åææ©å®¹æ¶åªè½æä¸ä¸ªçº¿ç¨æ§è¡, éè¿ CAS æ´æ° cellsBusy 置为 1 æ¥å®ç°ä¸ä¸ªé
transient volatile int cellsBusy;
```
工使µç¨ï¼
* cells å ç¨å
忝ç¸å¯¹æ¯è¾å¤§çï¼æ¯æ°æ§å è½½çï¼å¨æ ç«äºæè
å
¶ä»çº¿ç¨æ£å¨åå§å cells æ°ç»çæ
åµä¸ï¼ç´æ¥æ´æ° base å
* å¨ç¬¬ä¸æ¬¡åçç«äºæ¶ï¼casBase 失败ï¼ä¼å建ä¸ä¸ªå¤§å°ä¸º 2 ç cells æ°ç»ï¼å°å½åç´¯å çå¼å
è£
为 Cell å¯¹è±¡ï¼æ¾å
¥æ å°çæ§½ä½ä¸
* åæ®µç´¯å çè¿ç¨ä¸ï¼å¦æå½å线ç¨å¯¹åºç cells æ§½ä½ä¸ºç©ºï¼å°±ä¼æ°å»º Cell å¡«å
ï¼å¦æåºç°ç«äºï¼å°±ä¼éæ°è®¡ç®çº¿ç¨å¯¹åºçæ§½ä½ï¼ç»§ç»èªæå°è¯ä¿®æ¹
* åæ®µè¿ç§»åè¿åºç°ç«äºå°±ä¼æ©å®¹ cells æ°ç»é¿åº¦ä¸ºåæ¥ç两åï¼ç¶å rehashï¼**æ°ç»é¿åº¦æ»æ¯ 2 ç n 次å¹**ï¼é»è®¤æå¤§ä¸º CPU æ ¸æ°ï¼ä½æ¯å¯ä»¥è¶
è¿ï¼å¦ææ ¸æ°æ¯ 6 æ ¸ï¼æ°ç»æé¿æ¯ 8
æ¹æ³åæï¼
* LongAdder#addï¼ç´¯å æ¹æ³
```java
public void add(long x) {
// as 为累å åå
æ°ç»çå¼ç¨ï¼b 为åºç¡å¼ï¼v 表示ææå¼
// m 表示 cells æ°ç»çé¿åº¦ - 1ï¼a 表示å½å线ç¨å½ä¸ç cell åå
æ ¼
Cell[] as; long b, v; int m; Cell a;
// cells ä¸ä¸ºç©ºè¯´æ cells å·²ç»è¢«åå§åï¼çº¿ç¨åçäºç«äºï¼å»æ´æ°å¯¹åºç cell æ§½ä½
// è¿å
¥ || åçé»è¾å»æ´æ° base åï¼æ´æ°å¤±è´¥è¡¨ç¤ºåçç«äºè¿å
¥æ¡ä»¶
if ((as = cells) != null || !casBase(b = base, b + x)) {
// uncontended 为 true 表示 cell 没æç«äº
boolean uncontended = true;
// æ¡ä»¶ä¸: true 说æ cells æªåå§åï¼å¤çº¿ç¨å base åçç«äºéè¦è¿è¡åå§å cells æ°ç»
// fasle 说æ cells å·²ç»åå§åï¼è¿è¡ä¸ä¸ä¸ªæ¡ä»¶å¯»æ¾èªå·±ç cell å»ç´¯å
// æ¡ä»¶äº: getProbe() è·å hash å¼ï¼& m çé»è¾å HashMap çé»è¾ç¸åï¼ä¿è¯æ£åçååæ§
// true 说æå½å线ç¨å¯¹åºä¸æ ç cell 为空ï¼éè¦å建 cell
// false 说æå½å线ç¨å¯¹åºç cell ä¸ä¸ºç©ºï¼è¿è¡ä¸ä¸ä¸ªæ¡ä»¶ãå° x å¼ç´¯å å°å¯¹åºç cell ä¸ã
// æ¡ä»¶ä¸: æåå符å·ï¼false 说æ cas æåï¼ç´æ¥è¿åï¼true 说æå¤±è´¥ï¼å½å线ç¨å¯¹åºç cell æç«äº
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
longAccumulate(x, null, uncontended);
// ãuncontended å¨å¯¹åºç cell ä¸ç´¯å å¤±è´¥çæ¶åæä¸º falseï¼å
¶ä½æ
åµå为 trueã
}
}
```
* Striped64#longAccumulateï¼cell æ°ç»å建
```java
// x null false | true
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) {
int h;
// å½å线ç¨è¿æ²¡æå¯¹åºç cell, éè¦éæºçæä¸ä¸ª hash å¼ç¨æ¥å°å½å线ç¨ç»å®å° cell
if ((h = getProbe()) == 0) {
// åå§å probeï¼è·å hash å¼
ThreadLocalRandom.current();
h = getProbe();
// é»è®¤æ
åµä¸ å½å线ç¨è¯å®æ¯åå
¥å°äº cells[0] ä½ç½®ï¼ä¸æå®å½å䏿¬¡çæ£çç«äº
wasUncontended = true;
}
// è¡¨ç¤ºãæ©å®¹æåãï¼false ä¸å®ä¸ä¼æ©å®¹ï¼true å¯è½ä¼æ©å®¹
boolean collide = false;
//èªæ
for (;;) {
// as 表示cellså¼ç¨ï¼a 表示å½å线ç¨å½ä¸ç cellï¼n 表示 cells æ°ç»é¿åº¦ï¼v 表示 ææå¼
Cell[] as; Cell a; int n; long v;
// ãCASE1ã: 表示 cells å·²ç»åå§åäºï¼å½å线ç¨åºè¯¥å°æ°æ®åå
¥å°å¯¹åºç cell ä¸
if ((as = cells) != null && (n = as.length) > 0) {
// CASE1.1: true 表示å½å线ç¨å¯¹åºçç´¢å¼ä¸æ ç Cell 为 nullï¼éè¦å建 new Cell
if ((a = as[(n - 1) & h]) == null) {
// 夿 cellsBusy æ¯å¦è¢«é
if (cellsBusy == 0) {
// å建 cell, åå§ç´¯å å¼ä¸º x
Cell r = new Cell(x);
// å é
if (cellsBusy == 0 && casCellsBusy()) {
// å建æåæ è®°ï¼è¿å
¥ãå建 cell é»è¾ã
boolean created = false;
try {
Cell[] rs; int m, j;
// æå½å cells æ°ç»èµå¼ç» rsï¼å¹¶ä¸ä¸ä¸º null
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
// 忬¡å¤æé²æ¢å
¶å®çº¿ç¨åå§åè¿è¯¥ä½ç½®ï¼å½å线ç¨å次åå§å该ä½ç½®ä¼é ææ°æ®ä¸¢å¤±
// å 为è¿éæ¯çº¿ç¨å®å
¨ç夿ï¼è¿è¡çé»è¾ä¸ä¼è¢«å
¶ä»çº¿ç¨å½±å
rs[j = (m - 1) & h] == null) {
// ææ°å建ç cell å¡«å
è³å½åä½ç½®
rs[j] = r;
created = true; // 表示åå»ºå®æ
}
} finally {
cellsBusy = 0; // è§£é
}
if (created) // true 表示åå»ºå®æï¼å¯ä»¥æ¨åºå¾ªç¯äº
break;
continue;
}
}
collide = false;
}
// CASE1.2: æ¡ä»¶æç«è¯´æçº¿ç¨å¯¹åºç cell æç«äº, æ¹å线ç¨å¯¹åºç cell æ¥éè¯ cas
else if (!wasUncontended)
wasUncontended = true;
// CASE 1.3: å½åçº¿ç¨ rehash è¿ï¼å¦ææ°å½ä¸ç cell ä¸ä¸ºç©ºï¼å°±å°è¯ç´¯å ï¼false è¯´ææ°å½ä¸ä¹æç«äº
else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x))))
break;
// CASE 1.4: cells é¿åº¦å·²ç»è¶
è¿äºæå¤§é¿åº¦ CPU å
æ ¸çæ°éæè
å·²ç»æ©å®¹
else if (n >= NCPU || cells != as)
collide = false; // æ©å®¹æåæ¹ä¸ºfalseï¼ã表示ä¸è½æ©å®¹äºã
// CASE 1.5: æ´æ¹æ©å®¹æåï¼å¦æ n >= NCPUï¼è¿é就永è¿ä¸ä¼æ§è¡å°ï¼case1.4 æ°¸è¿å
äº 1.5 æ§è¡
else if (!collide)
collide = true;
// CASE 1.6: ãæ©å®¹é»è¾ãï¼è¿è¡å é
else if (cellsBusy == 0 && casCellsBusy()) {
try {
// 线ç¨å®å
¨çæ£æ¥ï¼é²æ¢æé´è¢«å
¶ä»çº¿ç¨æ©å®¹äº
if (cells == as) {
// æ©å®¹ä¸ºä»¥åç 2 å
Cell[] rs = new Cell[n << 1];
// éåç§»å¨å¼
for (int i = 0; i < n; ++i)
rs[i] = as[i];
// ææ©å®¹åçå¼ç¨ç» cells
cells = rs;
}
} finally {
cellsBusy = 0; // è§£é
}
collide = false; // æ©å®¹æåæ¹ä¸º falseï¼è¡¨ç¤ºä¸æ©å®¹äº
continue;
}
// éç½®å½åçº¿ç¨ Hash å¼ï¼è¿å°±æ¯ãåæ®µè¿ç§»æºå¶ã
h = advanceProbe(h);
}
// ãCASE2ã: è¿è¡å°è¿è¯´æ cells è¿æªåå§åï¼as 为null
// 夿æ¯å¦æ²¡æå éï¼æ²¡æå éå°±ç¨ CAS å é
// æ¡ä»¶äºå¤ææ¯å¦å
¶å®çº¿ç¨å¨å½å线ç¨ç» as èµå¼ä¹åä¿®æ¹äº cellsï¼è¿é䏿¯çº¿ç¨å®å
¨ç夿
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
// åå§åæ å¿ï¼å¼å§ ãåå§å cells æ°ç»ã
boolean init = false;
try {
// 忬¡å¤æ cells == as 鲿¢å
¶å®çº¿ç¨å·²ç»æååå§åäºï¼å½å线ç¨å次åå§å导è´ä¸¢å¤±æ°æ®
// å 为è¿éæ¯ã线ç¨å®å
¨çï¼éæ°æ£æ¥ï¼ç»å
¸ DCLã
if (cells == as) {
Cell[] rs = new Cell[2]; // åå§åæ°ç»å¤§å°ä¸º2
rs[h & 1] = new Cell(x); // å¡«å
线ç¨å¯¹åºçcell
cells = rs;
init = true; // åå§åæåï¼æ 记置为 true
}
} finally {
cellsBusy = 0; // è§£éå
}
if (init)
break; // åå§åæåç´æ¥è·³åºèªæ
}
// ãCASE3ã: è¿è¡å°è¿è¯´æå
¶ä»çº¿ç¨å¨åå§å cellsï¼å½å线ç¨å°å¼ç´¯å å° baseï¼ç´¯å æåç´æ¥ç»æèªæ
else if (casBase(v = base, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break;
}
}
```
* sumï¼è·åæç»ç»æéè¿ sum æ´åï¼**ä¿è¯æç»ä¸è´æ§ï¼ä¸ä¿è¯å¼ºä¸è´æ§**
```java
public long sum() {
Cell[] as = cells; Cell a;
long sum = base;
if (as != null) {
// éå ç´¯å
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}
```
***
### ABA
ABA é®é¢ï¼å½è¿è¡è·å主å
å弿¶ï¼è¯¥å
åå¼å¨åå
¥ä¸»å
åæ¶å·²ç»è¢«ä¿®æ¹äº N 次ï¼ä½æ¯æç»åæ¹æåæ¥çå¼
å
¶ä»çº¿ç¨å
æ A æ¹æ B åæ¹å Aï¼ä¸»çº¿ç¨**ä»
è½å¤æåºå
±äº«åéçå¼ä¸æåå¼ A æ¯å¦ç¸å**ï¼ä¸è½æç¥å°è¿ç§ä» A æ¹ä¸º B å æ¹å A çæ
åµï¼è¿æ¶ CAS è½ç¶æåï¼ä½æ¯è¿ç¨åå¨é®é¢
* æé æ¹æ³ï¼
* `public AtomicStampedReference(V initialRef, int initialStamp)`ï¼åå§å¼ååå§çæ¬å·
* 常ç¨APIï¼
* ` public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)`ï¼ææå¼ç¨åææçæ¬å·é½ä¸è´æè¿è¡ CAS ä¿®æ¹æ°æ®
* `public void set(V newReference, int newStamp)`ï¼è®¾ç½®å¼åçæ¬å·
* `public V getReference()`ï¼è¿åå¼ç¨çå¼
* `public int getStamp()`ï¼è¿åå½åçæ¬å·
```java
public static void main(String[] args) {
AtomicStampedReference atomicReference = new AtomicStampedReference<>(100,1);
int startStamp = atomicReference.getStamp();
new Thread(() ->{
int stamp = atomicReference.getStamp();
atomicReference.compareAndSet(100, 101, stamp, stamp + 1);
stamp = atomicReference.getStamp();
atomicReference.compareAndSet(101, 100, stamp, stamp + 1);
},"t1").start();
new Thread(() ->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!atomicReference.compareAndSet(100, 200, startStamp, startStamp + 1)) {
System.out.println(atomicReference.getReference());//100
System.out.println(Thread.currentThread().getName() + "线ç¨ä¿®æ¹å¤±è´¥");
}
},"t2").start();
}
```
***
### Unsafe
Unsafe æ¯ CAS çæ ¸å¿ç±»ï¼ç±äº Java æ æ³ç´æ¥è®¿é®åºå±ç³»ç»ï¼éè¦éè¿æ¬å°ï¼Nativeï¼æ¹æ³æ¥è®¿é®
Unsafe ç±»åå¨ sun.misc å
ï¼å
¶ä¸æææ¹æ³é½æ¯ native 修饰çï¼é½æ¯ç´æ¥è°ç¨**æä½ç³»ç»åºå±èµæº**æ§è¡ç¸åºçä»»å¡ï¼åºäºè¯¥ç±»å¯ä»¥ç´æ¥æä½ç¹å®çå
åæ°æ®ï¼å
¶å
鍿¹æ³æä½ç±»ä¼¼ C çæé
模æå®ç°ååæ´æ°ï¼
```java
public static void main(String[] args) {
MyAtomicInteger atomicInteger = new MyAtomicInteger(10);
if (atomicInteger.compareAndSwap(20)) {
System.out.println(atomicInteger.getValue());
}
}
class MyAtomicInteger {
private static final Unsafe UNSAFE;
private static final long VALUE_OFFSET;
private volatile int value;
static {
try {
//Unsafe unsafe = Unsafe.getUnsafe()è¿æ ·ä¼æ¥éï¼éè¦åå°è·å
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
// è·å value 屿§çå
åå°åï¼value 屿§æå该å°åï¼ç´æ¥è®¾ç½®è¯¥å°åçå¼å¯ä»¥ä¿®æ¹ value çå¼
VALUE_OFFSET = UNSAFE.objectFieldOffset(
MyAtomicInteger.class.getDeclaredField("value"));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public MyAtomicInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean compareAndSwap(int update) {
while (true) {
int prev = this.value;
int next = update;
// å½å对象 å
ååç§»é ææå¼ æ´æ°å¼
if (UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, prev, update)) {
System.out.println("CASæå");
return true;
}
}
}
}
```
***
### final
#### åç
```java
public class TestFinal {
final int a = 20;
}
```
åèç ï¼
```java
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: aload_0
5: bipush 20 // å°å¼ç´æ¥æ¾å
¥æ ä¸
7: putfield #2 // Field a:I
<-- åå±é
10: return
```
final åéçèµå¼éè¿ putfield æä»¤æ¥å®æï¼å¨è¿æ¡æä»¤ä¹åä¹ä¼å å
¥åå±éï¼ä¿è¯å¨å
¶å®çº¿ç¨è¯»å°å®ç弿¶ä¸ä¼åºç°ä¸º 0 çæ
åµ
å
¶ä»çº¿ç¨è®¿é® final 修饰çåé**ä¼å¤å¶ä¸ä»½æ¾å
¥æ ä¸**ï¼æçæ´é«
***
#### ä¸å¯å
ä¸å¯åï¼å¦æä¸ä¸ªå¯¹è±¡ä¸è½å¤ä¿®æ¹å
¶å
é¨ç¶æï¼å±æ§ï¼ï¼é£ä¹å°±æ¯ä¸å¯å对象
ä¸å¯å对象线ç¨å®å
¨çï¼ä¸åå¨å¹¶åä¿®æ¹åå¯è§æ§é®é¢ï¼æ¯å¦ä¸ç§é¿å
ç«äºçæ¹å¼
String ç±»ä¹æ¯ä¸å¯åçï¼è¯¥ç±»åç±»ä¸ææå±æ§é½æ¯ final ç
* ç±»ç¨ final 修饰ä¿è¯äºè¯¥ç±»ä¸çæ¹æ³ä¸è½è¢«è¦çï¼é²æ¢åç±»æ æé´ç ´åä¸å¯åæ§
* æ åå
¥æ¹æ³ï¼setï¼ç¡®ä¿å¤é¨ä¸è½å¯¹å
é¨å±æ§è¿è¡ä¿®æ¹
* 屿§ç¨ final 修饰ä¿è¯äºè¯¥å±æ§æ¯åªè¯»çï¼ä¸è½ä¿®æ¹
```java
public final class String
implements java.io.Serializable, Comparable, CharSequence {
/** The value is used for character storage. */
private final char value[];
//....
}
```
* æ´æ¹ String ç±»æ°æ®æ¶ï¼ä¼æé æ°å符串对象ï¼çææ°ç char[] valueï¼éè¿**åå»ºå¯æ¬å¯¹è±¡æ¥é¿å
å
±äº«çæ¹å¼ç§°ä¹ä¸ºä¿æ¤æ§æ·è´**
***
### State
æ ç¶æï¼æååéä¿åçæ°æ®ä¹å¯ä»¥ç§°ä¸ºç¶æä¿¡æ¯ï¼æ ç¶æå°±æ¯æ²¡ææååé
Servlet 为äºä¿è¯å
¶çº¿ç¨å®å
¨ï¼ä¸è¬ä¸ä¸º Servlet 设置æååéï¼è¿ç§æ²¡æä»»ä½æååéçç±»æ¯çº¿ç¨å®å
¨ç
***
### Local
#### åºæ¬ä»ç»
ThreadLocal ç±»ç¨æ¥æä¾çº¿ç¨å
é¨çå±é¨åéï¼è¿ç§åéå¨å¤çº¿ç¨ç¯å¢ä¸è®¿é®ï¼éè¿ get å set æ¹æ³è®¿é®ï¼æ¶è½ä¿è¯å个线ç¨çåéç¸å¯¹ç¬ç«äºå
¶ä»çº¿ç¨å
çåéï¼åé
å¨å å
ç **TLAB** ä¸
ThreadLocal å®ä¾é常æ¥è¯´é½æ¯ `private static` ç±»åçï¼å±äºä¸ä¸ªçº¿ç¨çæ¬å°åéï¼ç¨äºå
³è线ç¨å线ç¨ä¸ä¸æãæ¯ä¸ªçº¿ç¨é½ä¼å¨ ThreadLocal ä¸ä¿åä¸ä»½è¯¥çº¿ç¨ç¬æçæ°æ®ï¼æä»¥æ¯çº¿ç¨å®å
¨ç
ThreadLocal ä½ç¨ï¼
* 线ç¨å¹¶åï¼åºç¨å¨å¤çº¿ç¨å¹¶åçåºæ¯ä¸
* ä¼ éæ°æ®ï¼éè¿ ThreadLocal å®ç°å¨åä¸çº¿ç¨ä¸å彿°æç»ä»¶ä¸ä¼ éå
Œ
±åéï¼åå°ä¼ éå¤æåº¦
* 线ç¨éç¦»ï¼æ¯ä¸ªçº¿ç¨çåé齿¯ç¬ç«çï¼ä¸ä¼äºç¸å½±å
å¯¹æ¯ synchronizedï¼
| | synchronized | ThreadLocal |
| ------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| åç | 忥æºå¶éç¨**以æ¶é´æ¢ç©ºé´**çæ¹å¼ï¼åªæä¾äºä¸ä»½åéï¼è®©ä¸åççº¿ç¨æéè®¿é® | ThreadLocal éç¨**ä»¥ç©ºé´æ¢æ¶é´**çæ¹å¼ï¼ä¸ºæ¯ä¸ªçº¿ç¨é½æä¾äºä¸ä»½åéç坿¬ï¼ä»èå®ç°åæ¶è®¿é®èç¸ä¸å¹²æ° |
| ä¾§éç¹ | å¤ä¸ªçº¿ç¨ä¹é´è®¿é®èµæºç忥 | å¤çº¿ç¨ä¸è®©æ¯ä¸ªçº¿ç¨ä¹é´çæ°æ®ç¸äºé离 |
***
#### åºæ¬ä½¿ç¨
##### å¸¸ç¨æ¹æ³
| æ¹æ³ | æè¿° |
| -------------------------- | ---------------------------- |
| ThreadLocal<>() | å建 ThreadLocal 对象 |
| protected T initialValue() | è¿åå½å线ç¨å±é¨åéçåå§å¼ |
| public void set( T value) | 设置å½å线ç¨ç»å®çå±é¨åé |
| public T get() | è·åå½å线ç¨ç»å®çå±é¨åé |
| public void remove() | ç§»é¤å½å线ç¨ç»å®çå±é¨åé |
```java
public class MyDemo {
private static ThreadLocal tl = new ThreadLocal<>();
private String content;
private String getContent() {
// è·åå½å线ç¨ç»å®çåé
return tl.get();
}
private void setContent(String content) {
// åécontentç»å®å°å½å线ç¨
tl.set(content);
}
public static void main(String[] args) {
MyDemo demo = new MyDemo();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// è®¾ç½®æ°æ®
demo.setContent(Thread.currentThread().getName() + "çæ°æ®");
System.out.println("-----------------------");
System.out.println(Thread.currentThread().getName() + "--->" + demo.getContent());
}
});
thread.setName("线ç¨" + i);
thread.start();
}
}
}
```
***
##### åºç¨åºæ¯
ThreadLocal éç¨äºä¸é¢ä¸¤ç§åºæ¯ï¼
- æ¯ä¸ªçº¿ç¨éè¦æèªå·±åç¬çå®ä¾
- å®ä¾éè¦å¨å¤ä¸ªæ¹æ³ä¸å
±äº«ï¼ä½ä¸å¸æè¢«å¤çº¿ç¨å
񄧮
ThreadLocal æ¹æ¡æä¸¤ä¸ªçªåºçä¼å¿ï¼
1. ä¼ éæ°æ®ï¼ä¿åæ¯ä¸ªçº¿ç¨ç»å®çæ°æ®ï¼å¨éè¦çå°æ¹å¯ä»¥ç´æ¥è·åï¼é¿å
åæ°ç´æ¥ä¼ é带æ¥ç代ç è¦åé®é¢
2. 线ç¨é离ï¼å线ç¨ä¹é´çæ°æ®ç¸äºé离å´åå
·å¤å¹¶åæ§ï¼é¿å
忥æ¹å¼å¸¦æ¥çæ§è½æå¤±
ThreadLocal ç¨äºæ°æ®è¿æ¥çäºå¡ç®¡çï¼
```java
public class JdbcUtils {
// ThreadLocal对象ï¼å°connectionç»å®å¨å½å线ç¨ä¸
private static final ThreadLocal tl = new ThreadLocal();
// c3p0 æ°æ®åºè¿æ¥æ± å¯¹è±¡å±æ§
private static final ComboPooledDataSource ds = new ComboPooledDataSource();
// è·åè¿æ¥
public static Connection getConnection() throws SQLException {
//ååºå½å线ç¨ç»å®çconnection对象
Connection conn = tl.get();
if (conn == null) {
//å¦ææ²¡æï¼åä»è¿æ¥æ± ä¸ååº
conn = ds.getConnection();
//åå°connection对象ç»å®å°å½å线ç¨ä¸ï¼é常éè¦çæä½
tl.set(conn);
}
return conn;
}
// ...
}
```
ç¨ ThreadLocal 使 SimpleDateFormat ä»ç¬äº«åéåæå个线ç¨åéï¼
```java
public class ThreadLocalDateUtil {
private static ThreadLocal threadLocal = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static Date parse(String dateStr) throws ParseException {
return threadLocal.get().parse(dateStr);
}
public static String format(Date date) {
return threadLocal.get().format(date);
}
}
```
****
#### å®ç°åç
##### åºå±ç»æ
JDK8 以åï¼æ¯ä¸ª ThreadLocal é½å建ä¸ä¸ª Mapï¼ç¶åç¨çº¿ç¨ä½ä¸º Map ç keyï¼è¦åå¨çå±é¨åéä½ä¸º Map ç valueï¼è¾¾å°å个线ç¨çå±é¨åééç¦»çææãè¿ç§ç»æä¼é æ Map ç»æè¿å¤§åå
åæ³é²ï¼å 为 Thread åæ¢åæ æ³éè¿ key å é¤å¯¹åºçæ°æ®

JDK8 以åï¼æ¯ä¸ª Thread ç»´æ¤ä¸ä¸ª ThreadLocalMapï¼è¿ä¸ª Map ç key æ¯ ThreadLocal å®ä¾æ¬èº«ï¼value æ¯çæ£è¦åå¨çå¼
* **æ¯ä¸ª Thread 线ç¨å
é¨é½æä¸ä¸ª Map (ThreadLocalMap)**
* Map éé¢åå¨ ThreadLocal 对象ï¼keyï¼å线ç¨çç§æåéï¼valueï¼
* Thread å
é¨ç Map æ¯ç± ThreadLocal ç»´æ¤çï¼ç± ThreadLocal è´è´£å map è·åå设置线ç¨çåéå¼
* 对äºä¸åç线ç¨ï¼æ¯æ¬¡è·å坿¬å¼æ¶ï¼å«ç线ç¨å¹¶ä¸è½è·åå°å½å线ç¨ç坿¬å¼ï¼å½¢æå¯æ¬çé离ï¼äºä¸å¹²æ°

JDK8 åå对æ¯ï¼
* æ¯ä¸ª Map åå¨ç Entry æ°éä¼åå°ï¼å 为ä¹åçå卿°éç± Thread çæ°éå³å®ï¼ç°å¨ç± ThreadLocal çæ°éå³å®ï¼å¨å®é
ç¼ç¨å½ä¸ï¼å¾å¾ ThreadLocal çæ°éè¦å°äº Thread çæ°é
* å½ Thread 鿝ä¹åï¼å¯¹åºç ThreadLocalMap ä¹ä¼éä¹éæ¯ï¼è½åå°å
åç使ç¨ï¼**鲿¢å
åæ³é²**
***
##### æååé
* Thread ç±»çç¸å
³å±æ§ï¼**æ¯ä¸ä¸ªçº¿ç¨ææä¸ä¸ª ThreadLocalMap 对象**ï¼åæ¾ç± ThreadLocal åæ°æ®ç»æç Entry é®å¼å¯¹
```java
ThreadLocal.ThreadLocalMap threadLocals = null
```
* è®¡ç® ThreadLocal 对象çåå¸å¼ï¼
```java
private final int threadLocalHashCode = nextHashCode()
```
ä½¿ç¨ `threadLocalHashCode & (table.length - 1)` 计ç®å½å entry éè¦åæ¾çä½ç½®
* æ¯å建ä¸ä¸ª ThreadLocal 对象就ä¼ä½¿ç¨ nextHashCode åé
ä¸ä¸ª hash å¼ç»è¿ä¸ªå¯¹è±¡ï¼
```java
private static AtomicInteger nextHashCode = new AtomicInteger()
```
* ææ³¢é£å¥æ°ä¹å«é»éå岿°ï¼hash ç**å¢é**å°±æ¯è¿ä¸ªæ°åï¼å¸¦æ¥ç好夿¯ hash åå¸é常ååï¼
```java
private static final int HASH_INCREMENT = 0x61c88647
```
***
##### æåæ¹æ³
æ¹æ³é½æ¯çº¿ç¨å®å
¨çï¼å 为 ThreadLocal å±äºä¸ä¸ªçº¿ç¨çï¼ThreadLocal ä¸çæ¹æ³ï¼é»è¾é½æ¯è·åå½å线ç¨ç»´æ¤ç ThreadLocalMap 对象ï¼ç¶åè¿è¡æ°æ®çå¢å æ¹æ¥ï¼æ²¡ææå®åå§å¼ç threadlcoal 对象é»è®¤èµå¼ä¸º null
* initialValue()ï¼è¿å该线ç¨å±é¨åéçåå§å¼
* å»¶è¿è°ç¨çæ¹æ³ï¼å¨æ§è¡ get æ¹æ³æ¶ææ§è¡
* è¯¥æ¹æ³ç¼ºçï¼é»è®¤ï¼å®ç°ç´æ¥è¿åä¸ä¸ª null
* 妿æ³è¦ä¸ä¸ªåå§å¼ï¼å¯ä»¥éåæ¤æ¹æ³ï¼ è¯¥æ¹æ³æ¯ä¸ä¸ª `protected` çæ¹æ³ï¼ä¸ºäºè®©åç±»è¦çè设计ç
```java
protected T initialValue() {
return null;
}
```
* nextHashCode()ï¼è®¡ç®åå¸å¼ï¼ThreadLocal çæ£åæ¹å¼ç§°ä¹ä¸º**ææ³¢é£å¥æ£å**ï¼æ¯æ¬¡è·ååå¸å¼é½ä¼å ä¸ HASH_INCREMENTï¼è¿æ ·åå¯ä»¥å°½éé¿å
hash å²çªï¼è®©åå¸å¼è½ååçåå¸å¨ 2 ç n 次æ¹çæ°ç»ä¸
```java
private static int nextHashCode() {
// åå¸å¼èªå¢ä¸ä¸ª HASH_INCREMENT æ°å¼
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
```
* set()ï¼ä¿®æ¹å½å线ç¨ä¸å½å threadlocal 对象ç¸å
³èç线ç¨å±é¨åé
```java
public void set(T value) {
// è·åå½å线ç¨å¯¹è±¡
Thread t = Thread.currentThread();
// è·åæ¤çº¿ç¨å¯¹è±¡ä¸ç»´æ¤ç ThreadLocalMap 对象
ThreadLocalMap map = getMap(t);
// 夿 map æ¯å¦åå¨
if (map != null)
// è°ç¨ threadLocalMap.set æ¹æ³è¿è¡éåæè
æ·»å
map.set(this, value);
else
// map 为空ï¼è°ç¨ createMap è¿è¡ ThreadLocalMap 对象çåå§åãåæ°1æ¯å½å线ç¨ï¼åæ°2æ¯å±é¨åé
createMap(t, value);
}
```
```java
// è·åå½åçº¿ç¨ Thread 对åºç»´æ¤ç ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
// å建å½å线ç¨Thread对åºç»´æ¤çThreadLocalMap
void createMap(Thread t, T firstValue) {
// ãè¿éç this æ¯è°ç¨æ¤æ¹æ³ç threadLocalãï¼å建ä¸ä¸ªæ°ç Map 并设置第ä¸ä¸ªæ°æ®
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
```
* get()ï¼è·åå½å线ç¨ä¸å½å ThreadLocal 对象ç¸å
³èç线ç¨å±é¨åé
```java
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
// 妿æ¤mapåå¨
if (map != null) {
// 以å½åç ThreadLocal 为 keyï¼è°ç¨ getEntry è·å对åºçåå¨å®ä½ e
ThreadLocalMap.Entry e = map.getEntry(this);
// 对 e è¿è¡å¤ç©º
if (e != null) {
// è·ååå¨å®ä½ e 对åºç valueå¼
T result = (T)e.value;
return result;
}
}
/*æä¸¤ç§æ
嵿æ§è¡å½å代ç
第ä¸ç§æ
åµ: map ä¸åå¨ï¼è¡¨ç¤ºæ¤çº¿ç¨æ²¡æç»´æ¤ç ThreadLocalMap 对象
第äºç§æ
åµ: map åå¨, 使¯ã没æä¸å½å ThreadLocal å
³èç entryãï¼å°±ä¼è®¾ç½®ä¸ºé»è®¤å¼ */
// åå§åå½å线ç¨ä¸å½å threadLocal 对象ç¸å
³èç value
return setInitialValue();
}
```
```java
private T setInitialValue() {
// è°ç¨initialValueè·ååå§åçå¼ï¼æ¤æ¹æ³å¯ä»¥è¢«åç±»éå, 妿ä¸éåé»è®¤è¿å null
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
// 夿 map æ¯å¦åå§åè¿
if (map != null)
// åå¨åè°ç¨ map.set 设置æ¤å®ä½ entryï¼value æ¯é»è®¤çå¼
map.set(this, value);
else
// è°ç¨ createMap è¿è¡ ThreadLocalMap 对象çåå§åä¸
createMap(t, value);
// è¿å线ç¨ä¸å½å threadLocal å
³èçå±é¨åé
return value;
}
```
* remove()ï¼ç§»é¤å½å线ç¨ä¸å½å threadLocal 对象ç¸å
³èç线ç¨å±é¨åé
```java
public void remove() {
// è·åå½å线ç¨å¯¹è±¡ä¸ç»´æ¤ç ThreadLocalMap 对象
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
// map åå¨åè°ç¨ map.removeï¼thisæ¶å½åThreadLocalï¼ä»¥this为keyå é¤å¯¹åºçå®ä½
m.remove(this);
}
```
***
#### LocalMap
##### æå屿§
ThreadLocalMap æ¯ ThreadLocal çå
é¨ç±»ï¼æ²¡æå®ç° Map æ¥å£ï¼ç¨ç¬ç«çæ¹å¼å®ç°äº Map çåè½ï¼å
¶å
é¨ Entry 乿¯ç¬ç«å®ç°
```java
// åå§åå½å map å
鍿£å表æ°ç»çåå§é¿åº¦ 16
private static final int INITIAL_CAPACITY = 16;
// åæ¾æ°æ®çtableï¼æ°ç»é¿åº¦å¿
é¡»æ¯2çæ´æ¬¡å¹ã
private Entry[] table;
// æ°ç»éé¢ entrys ç个æ°ï¼å¯ä»¥ç¨äºå¤æ table å½å使ç¨éæ¯å¦è¶
è¿éå¼
private int size = 0;
// è¿è¡æ©å®¹çéå¼ï¼è¡¨ä½¿ç¨é大äºå®çæ¶åè¿è¡æ©å®¹ã
private int threshold;
```
åå¨ç»æ Entryï¼
* Entry ç»§æ¿ WeakReferenceï¼key æ¯å¼±å¼ç¨ï¼ç®çæ¯å° ThreadLocal 对象ççå½å¨æå线ç¨çå½å¨æè§£ç»
* Entry éå¶åªè½ç¨ ThreadLocal ä½ä¸º keyï¼key 为 null (entry.get() == null) æå³ç key ä¸å被å¼ç¨ï¼entry ä¹å¯ä»¥ä» table 䏿¸
é¤
```java
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal> k, Object v) {
// this.referent = referent = key;
super(k);
value = v;
}
}
```
æé æ¹æ³ï¼å»¶è¿åå§åçï¼çº¿ç¨ç¬¬ä¸æ¬¡åå¨ threadLocal - value æ¶æä¼å建 threadLocalMap 对象
```java
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
// åå§åtableï¼å建ä¸ä¸ªé¿åº¦ä¸º16çEntryæ°ç»
table = new Entry[INITIAL_CAPACITY];
// ã寻åç®æ³ã计ç®ç´¢å¼
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
// å建 entry 对象ï¼åæ¾å°æå®ä½ç½®ç slot ä¸
table[i] = new Entry(firstKey, firstValue);
// æ°æ®æ»éæ¯ 1
size = 1;
// å°éå¼è®¾ç½®ä¸º ï¼å½åæ°ç»é¿åº¦ * 2ï¼/ 3ã
setThreshold(INITIAL_CAPACITY);
}
```
***
##### æåæ¹æ³
* set()ï¼æ·»å æ°æ®ï¼ThreadLocalMap 使ç¨**çº¿æ§æ¢æµæ³æ¥è§£å³åå¸å²çª**
* è¯¥æ¹æ³ä¼ä¸ç´æ¢æµä¸ä¸ä¸ªå°åï¼ç´å°æç©ºçå°ååæå
¥ï¼è¥æå
¥å Map æ°éè¶
è¿éå¼ï¼æ°ç»ä¼æ©å®¹ä¸ºåæ¥ç 2 å
å设å½å table é¿åº¦ä¸º16ï¼è®¡ç®åºæ¥ key ç hash å¼ä¸º 14ï¼å¦æ table[14] ä¸å·²ç»æå¼ï¼å¹¶ä¸å
¶ key ä¸å½å key ä¸ä¸è´ï¼é£ä¹å°±åçäº hash å²çªï¼è¿ä¸ªæ¶åå° 14 å 1 å¾å° 15ï¼å table[15] è¿è¡å¤æï¼å¦æè¿æ¯å²çªä¼åå° 0ï¼å table[0]ï¼ä»¥æ¤ç±»æ¨ï¼ç´å°å¯ä»¥æå
¥ï¼å¯ä»¥æ Entry[] table çæä¸ä¸ª**ç¯å½¢æ°ç»**
* çº¿æ§æ¢æµæ³ä¼åºç°**å 积é®é¢**ï¼å¯ä»¥éåå¹³æ¹æ¢æµæ³è§£å³
* 卿¢æµè¿ç¨ä¸ ThreadLocal ä¼å¤ç¨ key 为 null çè Entry 对象ï¼å¹¶è¿è¡å徿¸
çï¼é²æ¢åºç°å
åæ³æ¼
```java
private void set(ThreadLocal> key, Object value) {
// è·åæ£å表
ThreadLocal.ThreadLocalMap.Entry[] tab = table;
int len = tab.length;
// åå¸å¯»å
int i = key.threadLocalHashCode & (len-1);
// 使ç¨çº¿æ§æ¢æµæ³å忥æ¾å
ç´ ï¼ç¢°å° entry 为空æ¶åæ¢æ¢æµ
for (ThreadLocal.ThreadLocalMap.Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
// è·åå½åå
ç´ key
ThreadLocal> k = e.get();
// ThreadLocal 对åºç key åå¨ï¼ãç´æ¥è¦çä¹åçå¼ã
if (k == key) {
e.value = value;
return;
}
// ãè¿ä¸¤ä¸ªæ¡ä»¶è°å
æç«ä¸ä¸å®ï¼æä»¥ replaceStaleEntry ä¸è¿éè¦å¤æ k == key çæ
åµã
// key 为 nullï¼ä½æ¯å¼ä¸ä¸º nullï¼è¯´æä¹åç ThreadLocal 对象已ç»è¢«åæ¶äºï¼å½åæ¯ãè¿ææ°æ®ã
if (k == null) {
// ã碰å°ä¸ä¸ªè¿æç slotï¼å½åæ°æ®å¤ç¨è¯¥æ§½ä½ï¼æ¿æ¢è¿ææ°æ®ã
// è¿ä¸ªæ¹æ³è¿è¿è¡äºå徿¸
çå¨ä½ï¼é²æ¢å
åæ³æ¼
replaceStaleEntry(key, value, i);
return;
}
}
// é»è¾å°è¿è¯´æç¢°å° slot == null çä½ç½®ï¼åå¨ç©ºå
ç´ çä½ç½®å建ä¸ä¸ªæ°ç Entry
tab[i] = new Entry(key, value);
// æ°é + 1
int sz = ++size;
// ãå䏿¬¡å¯å弿¸
çãï¼å¦ææ²¡ææ¸
é¤ä»»ä½ entry å¹¶ä¸ãå½å使ç¨éè¾¾å°äºè´è½½å åæå®ä¹ï¼é£ä¹è¿è¡ rehash
if (!cleanSomeSlots(i, sz) && sz >= threshold)
// æ©å®¹
rehash();
}
```
```java
// è·åãç¯å½¢æ°ç»ãçä¸ä¸ä¸ªç´¢å¼
private static int nextIndex(int i, int len) {
// ç´¢å¼è¶çåä» 0 å¼å§ç»§ç»è·å
return ((i + 1 < len) ? i + 1 : 0);
}
```
```java
// 卿å®ä½ç½®æå
¥æå®çæ°æ®
private void replaceStaleEntry(ThreadLocal> key, Object value, int staleSlot) {
// è·åæ£å表
Entry[] tab = table;
int len = tab.length;
Entry e;
// æ¢æµå¼æ¸
ççå¼å§ä¸æ ï¼é»è®¤ä»å½å staleSlot å¼å§
int slotToExpunge = staleSlot;
// 以å½å staleSlot å¼å§ãååè¿ä»£æ¥æ¾ãï¼æ¾å°ç´¢å¼é åè¿ææ°æ®ï¼æ¾å°ä»¥åæ¿æ¢ slotToExpunge å¼
// ãä¿è¯å¨ä¸ä¸ªåºé´æ®µå
ï¼ä»æåé¢çè¿ææ°æ®å¼å§æ¸
çã
for (int i = prevIndex(staleSlot, len); (e = tab[i]) != null; i = prevIndex(i, len))
if (e.get() == null)
slotToExpunge = i;
// 以 staleSlot ãåå廿¥æ¾ãï¼ç´å°ç¢°å° null 为æ¢ï¼è¿æ¯çº¿æ§æ¢æµ
for (int i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
// è·åå½åèç¹ç key
ThreadLocal> k = e.get();
// æ¡ä»¶æç«è¯´ææ¯ãæ¿æ¢é»è¾ã
if (k == key) {
e.value = value;
// å ä¸ºæ¬æ¥è¦å¨ staleSlot ç´¢å¼å¤æå
¥è¯¥æ°æ®ï¼ç°å¨æ¾å°äºiç´¢å¼å¤çkey䏿°æ®ä¸è´
// 使¯ i ä½ç½®è·ç¦»æ£ç¡®çä½ç½®æ´è¿ï¼å 为æ¯å忥æ¾ï¼æä»¥è¿æ¯è¦å¨ staleSlot ä½ç½®æå
¥å½å entry
// ç¶åå° table[staleSlot] è¿ä¸ªè¿ææ°æ®æ¾å°å½å循ç¯å°ç table[i] è¿ä¸ªä½ç½®ï¼
tab[i] = tab[staleSlot];
tab[staleSlot] = e;
// æ¡ä»¶æç«è¯´æå忥æ¾è¿ææ°æ®å¹¶æªæ¾å°è¿æç entryï¼ä½ staleSlot ä½ç½®å·²ç»ä¸æ¯è¿ææ°æ®äºï¼i ä½ç½®ææ¯
if (slotToExpunge == staleSlot)
slotToExpunge = i;
// ãæ¸
çè¿ææ°æ®ï¼expungeStaleEntry æ¢æµå¼æ¸
çï¼cleanSomeSlots å¯å弿¸
çã
cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
return;
}
// æ¡ä»¶æç«è¯´æå½åéåç entry æ¯ä¸ä¸ªè¿ææ°æ®ï¼å¹¶ä¸è¯¥ä½ç½®åé¢ä¹æ²¡æè¿ææ°æ®
if (k == null && slotToExpunge == staleSlot)
// æ¢æµå¼æ¸
çè¿ææ°æ®çå¼å§ä¸æ ä¿®æ¹ä¸ºå½å循ç¯ç indexï¼å 为 staleSlot 伿¾å
¥è¦æ·»å çæ°æ®
slotToExpunge = i;
}
// å忥æ¾è¿ç¨ä¸å¹¶æªåç° k == key ç entryï¼è¯´æå½åæ¯ä¸ä¸ªãåä»£è¿ææ°æ®é»è¾ã
// å é¤åæçæ°æ®å¼ç¨ï¼é²æ¢å
åæ³é²
tab[staleSlot].value = null;
// staleSlot ä½ç½®æ·»å æ°æ®ï¼ãä¸é¢çææé»è¾é½ä¸ä¼æ´æ¹ staleSlot çå¼ã
tab[staleSlot] = new Entry(key, value);
// æ¡ä»¶æç«è¯´æé¤äº staleSlot 以å¤ï¼è¿åç°å
¶å®çè¿æ slotï¼æä»¥è¦ãå¼å¯æ¸
çæ°æ®çé»è¾ã
if (slotToExpunge != staleSlot)
cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
}
```

```java
private static int prevIndex(int i, int len) {
// å½¢æä¸ä¸ªç¯ç»å¼ç访é®ï¼å¤´ç´¢å¼è¶çå置为尾索å¼
return ((i - 1 >= 0) ? i - 1 : len - 1);
}
```
* getEntry()ï¼ThreadLocal ç get æ¹æ³ä»¥å½åç ThreadLocal 为 keyï¼è°ç¨ getEntry è·å对åºçåå¨å®ä½ e
```java
private Entry getEntry(ThreadLocal> key) {
// åå¸å¯»å
int i = key.threadLocalHashCode & (table.length - 1);
// è®¿é®æ£åè¡¨ä¸æå®æå®ä½ç½®ç slot
Entry e = table[i];
// æ¡ä»¶æç«ï¼è¯´æ slot æå¼å¹¶ä¸ key å°±æ¯è¦å¯»æ¾ç keyï¼ç´æ¥è¿å
if (e != null && e.get() == key)
return e;
else
// è¿è¡çº¿æ§æ¢æµ
return getEntryAfterMiss(key, i, e);
}
// çº¿æ§æ¢æµå¯»å
private Entry getEntryAfterMiss(ThreadLocal> key, int i, Entry e) {
// è·åæ£å表
Entry[] tab = table;
int len = tab.length;
// å¼å§éåï¼ç¢°å° slot == null çæ
åµï¼æç´¢ç»æ
while (e != null) {
// è·åå½å slot ä¸ entry 对象ç key
ThreadLocal> k = e.get();
// æ¡ä»¶æç«è¯´ææ¾å°äºï¼ç´æ¥è¿å
if (k == key)
return e;
if (k == null)
// è¿ææ°æ®ï¼ãæ¢æµå¼è¿ææ°æ®åæ¶ã
expungeStaleEntry(i);
else
// æ´æ° index ç»§ç»ååèµ°
i = nextIndex(i, len);
// è·åä¸ä¸ä¸ªæ§½ä½ä¸ç entry
e = tab[i];
}
// 说æå½ååºæ®µæ²¡ææ¾å°ç¸åºæ°æ®
// ãå ä¸ºåæ¾æ°æ®æ¯çº¿æ§çååå¯»æ¾æ§½ä½ï¼é½æ¯ç´§æ¨ççï¼ä¸å¯è½è¶è¿ä¸ä¸ª ç©ºæ§½ä½ å¨å颿¾ãï¼å¯ä»¥åå°éåçæ¬¡æ°
return null;
}
```
* rehash()ï¼è§¦å䏿¬¡å
¨éæ¸
çï¼å¦ææ°ç»é¿åº¦å¤§äºçäºé¿åº¦ç `2/3 * 3/4 = 1/2`ï¼åè¿è¡ resize
```java
private void rehash() {
// æ¸
æ¥å½åæ£å表å
çãææãè¿æçæ°æ®
expungeStaleEntries();
// threshold = len * 2 / 3ï¼å°±æ¯ 2/3 * (1 - 1/4)
if (size >= threshold - threshold / 4)
resize();
}
```
```java
private void expungeStaleEntries() {
Entry[] tab = table;
int len = tab.length;
// ãéåææçæ§½ä½ï¼æ¸
çè¿ææ°æ®ã
for (int j = 0; j < len; j++) {
Entry e = tab[j];
if (e != null && e.get() == null)
expungeStaleEntry(j);
}
}
```
Entry **æ°ç»ä¸ºæ©å®¹ä¸ºåæ¥ç 2 å** ï¼éæ°è®¡ç® key çæ£åå¼ï¼å¦æéå° key 为 null çæ
åµï¼ä¼å°å
¶ value ä¹ç½®ä¸º nullï¼å¸®å© GC
```java
private void resize() {
Entry[] oldTab = table;
int oldLen = oldTab.length;
// æ°æ°ç»çé¿åº¦æ¯èæ°ç»çäºå
int newLen = oldLen * 2;
Entry[] newTab = new Entry[newLen];
// ç»è®¡æ°tableä¸çentryæ°é
int count = 0;
// éåè表ï¼è¿è¡ãæ°æ®è¿ç§»ã
for (int j = 0; j < oldLen; ++j) {
// 访é®è表çæå®ä½ç½®ç entry
Entry e = oldTab[j];
// æ¡ä»¶æç«è¯´æè表ä¸è¯¥ä½ç½®ææ°æ®ï¼å¯è½æ¯è¿ææ°æ®ä¹å¯è½ä¸æ¯
if (e != null) {
ThreadLocal> k = e.get();
// è¿ææ°æ®
if (k == null) {
e.value = null; // Help the GC
} else {
// éè¿ææ°æ®ï¼å¨æ°è¡¨ä¸è¿è¡åå¸å¯»å
int h = k.threadLocalHashCode & (newLen - 1);
// ãçº¿ç¨æ¢æµã
while (newTab[h] != null)
h = nextIndex(h, newLen);
// å°æ°æ®åæ¾å°æ°è¡¨åéç slot ä¸
newTab[h] = e;
count++;
}
}
}
// 设置ä¸ä¸æ¬¡è§¦åæ©å®¹çææ ï¼threshold = len * 2 / 3;
setThreshold(newLen);
size = count;
// å°æ©å®¹åçæ°è¡¨èµå¼ç» threadLocalMap å
鍿£å表æ°ç»å¼ç¨
table = newTab;
}
```
* remove()ï¼å é¤ Entry
```java
private void remove(ThreadLocal> key) {
Entry[] tab = table;
int len = tab.length;
// åå¸å¯»å
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
// æ¾å°äºå¯¹åºç key
if (e.get() == key) {
// 设置 key 为 null
e.clear();
// æ¢æµå¼æ¸
ç
expungeStaleEntry(i);
return;
}
}
}
```
***
##### æ¸
çæ¹æ³
* æ¢æµå¼æ¸
çï¼æ²¿çå¼å§ä½ç½®ååæ¢æµæ¸
çè¿ææ°æ®ï¼æ²¿éä¸ç¢°å°æªè¿ææ°æ®åå°æ¤æ°æ® rehash å¨ table æ°ç»ä¸çå®ä½ï¼éå®ä½åçå
ç´ çè®ºä¸æ´æ¥è¿ `i = entry.key & (table.length - 1)`ï¼è®©**æ°æ®çæåæ´ç´§å**ï¼ä¼ä¼åæ´ä¸ªæ£å表æ¥è¯¢æ§è½
```java
// table[staleSlot] æ¯ä¸ä¸ªè¿ææ°æ®ï¼ä»¥è¿ä¸ªä½ç½®å¼å§ç»§ç»å忥æ¾è¿ææ°æ®
private int expungeStaleEntry(int staleSlot) {
// è·åæ£åè¡¨åæ°ç»é¿åº¦
Entry[] tab = table;
int len = tab.length;
// help gcï¼å
æå½åè¿æç entry 置空ï¼å¨åæ¶å¯¹ entry çå¼ç¨
tab[staleSlot].value = null;
tab[staleSlot] = null;
// æ°é-1
size--;
Entry e;
int i;
// ä» staleSlot å¼å§ååéåï¼ç´å°ç¢°å° slot == null ç»æï¼ãåºé´å
æ¸
çè¿ææ°æ®ã
for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
ThreadLocal> k = e.get();
// å½å entry æ¯è¿ææ°æ®
if (k == null) {
// help gc
e.value = null;
tab[i] = null;
size--;
} else {
// å½å entry 䏿¯è¿ææ°æ®çé»è¾ï¼ãrehashã
// éæ°è®¡ç®å½å entry 对åºç index
int h = k.threadLocalHashCode & (len - 1);
// æ¡ä»¶æç«è¯´æå½å entry å卿¶åçè¿ hash å²çªï¼åååç§»è¿äº
if (h != i) {
// å½åä½ç½®ç½®ç©º
tab[i] = null;
// 以æ£ç¡®ä½ç½® h å¼å§ï¼å忥æ¾ç¬¬ä¸ä¸ªå¯ä»¥åæ¾ entry çä½ç½®
while (tab[h] != null)
h = nextIndex(h, len);
// å°å½åå
ç´ æ¾å
¥å°ãè·ç¦»æ£ç¡®ä½ç½®æ´è¿çä½ç½®ï¼æå¯è½å°±æ¯æ£ç¡®ä½ç½®ã
tab[h] = e;
}
}
}
// è¿å slot = null çæ§½ä½ç´¢å¼ï¼å¾ä¾æ¯ 7ï¼è¿ä¸ªç´¢å¼ä»£è¡¨ãç´¢å¼åé¢çåºé´å·²ç»æ¸
ç宿åå¾äºã
return i;
}
```
* å¯å弿¸
çï¼ååå¾ªç¯æ«æè¿ææ°æ®ï¼åç°è¿ææ°æ®è°ç¨æ¢æµå¼æ¸
çæ¹æ³ï¼å¦æè¿ç»å 次ç循ç¯é½æ²¡æåç°è¿ææ°æ®ï¼å°±åæ¢æ«æ
```java
// i 表示å¯å弿¸
çå·¥ä½å¼å§ä½ç½®ï¼ä¸è¬æ¯ç©º slotï¼n ä¸è¬ä¼ éçæ¯ table.length
private boolean cleanSomeSlots(int i, int n) {
// 表示å¯å弿¸
ç工使¯å¦æ¸
é¤äºè¿ææ°æ®
boolean removed = false;
// è·åå½å map çæ£å表å¼ç¨
Entry[] tab = table;
int len = tab.length;
do {
// è·åä¸ä¸ä¸ªç´¢å¼ï¼å ä¸ºæ¢æµå¼è¿åç slot 为 null
i = nextIndex(i, len);
Entry e = tab[i];
// æ¡ä»¶æç«è¯´ææ¯è¿æçæ°æ®ï¼key 被 gc äº
if (e != null && e.get() == null) {
// ãåç°è¿ææ°æ®éç½® n 为æ°ç»çé¿åº¦ã
n = len;
// 表示æ¸
çè¿è¿ææ°æ®
removed = true;
// 以å½åè¿æç slot 为å¼å§èç¹ å䏿¬¡æ¢æµå¼æ¸
çå·¥ä½
i = expungeStaleEntry(i);
}
// å设 table é¿åº¦ä¸º 16
// 16 >>> 1 ==> 8ï¼8 >>> 1 ==> 4ï¼4 >>> 1 ==> 2ï¼2 >>> 1 ==> 1ï¼1 >>> 1 ==> 0
// è¿ç»ç»è¿è¿ä¹å¤æ¬¡å¾ªç¯ãæ²¡ææ«æå°è¿ææ°æ®ãï¼å°±åæ¢å¾ªç¯ï¼æ«æå°ç©º slot ä¸ç®ï¼å ä¸ºä¸æ¯è¿ææ°æ®
} while ((n >>>= 1) != 0);
// è¿åæ¸
餿 è®°
return removed;
}
```
åèè§é¢ï¼https://space.bilibili.com/457326371/
***
#### å
åæ³æ¼
Memory leakï¼å
åæ³æ¼æ¯æç¨åºä¸å¨æåé
çå å
åç±äºæç§åå æªéæ¾ææ æ³éæ¾ï¼é æç³»ç»å
åçæµªè´¹ï¼å¯¼è´ç¨åºè¿è¡é度åæ
¢çè³ç³»ç»å´©æºç严éåæï¼å
åæ³æ¼çå 积ç»å°å¯¼è´å
åæº¢åº
* 妿 key 使ç¨å¼ºå¼ç¨ï¼ä½¿ç¨å® ThreadLocal ï¼threadLocal Ref è¢«åæ¶ï¼ä½æ¯ threadLocalMap ç Entry 强å¼ç¨äº threadLocalï¼é æ threadLocal æ æ³è¢«åæ¶ï¼æ æ³å®å
¨é¿å
å
åæ³æ¼
* 妿 key 使ç¨å¼±å¼ç¨ï¼ä½¿ç¨å® ThreadLocal ï¼threadLocal Ref è¢«åæ¶ï¼ThreadLocalMap åªææ ThreadLocal çå¼±å¼ç¨ï¼æä»¥threadlocal ä¹å¯ä»¥è¢«åæ¶ï¼æ¤æ¶ Entry ä¸ç key = nullã使²¡ææå¨å é¤è¿ä¸ª Entry æè
CurrentThread ä¾ç¶è¿è¡ï¼ä¾ç¶åå¨å¼ºå¼ç¨é¾ï¼value ä¸ä¼è¢«åæ¶ï¼èè¿å value æ°¸è¿ä¸ä¼è¢«è®¿é®å°ï¼ä¹ä¼å¯¼è´ value å
åæ³æ¼
* 两个主è¦åå ï¼
* 没ææå¨å é¤è¿ä¸ª Entry
* CurrentThread ä¾ç¶è¿è¡
æ ¹æ¬åå ï¼ThreadLocalMap æ¯ Threadçä¸ä¸ªå±æ§ï¼**çå½å¨æè· Thread 䏿 ·é¿**ï¼å¦ææ²¡ææå¨å é¤å¯¹åº Entry å°±ä¼å¯¼è´å
åæ³æ¼
è§£å³æ¹æ³ï¼ä½¿ç¨å® ThreadLocal ä¸åå¨çå
容åå°å® remove æå°±å¯ä»¥
ThreadLocal å
é¨è§£å³æ¹æ³ï¼å¨ ThreadLocalMap ä¸ç set/getEntry æ¹æ³ä¸ï¼éè¿çº¿æ§æ¢æµæ³å¯¹ key è¿è¡å¤æï¼å¦æ key 为 nullï¼ThreadLocal 为 nullï¼ä¼å¯¹ Entry è¿è¡åå¾åæ¶ãæä»¥**使ç¨å¼±å¼ç¨æ¯å¼ºå¼ç¨å¤ä¸å±ä¿é**ï¼å°±ç®ä¸è°ç¨ removeï¼ä¹ææºä¼è¿è¡ GC
***
#### åéä¼ é
##### åºæ¬ä½¿ç¨
ç¶å线ç¨ï¼**å建å线ç¨ççº¿ç¨æ¯ç¶çº¿ç¨**ï¼æ¯å¦å®ä¾ä¸ç main 线ç¨å°±æ¯ç¶çº¿ç¨
ThreadLocal ä¸åå¨çæ¯çº¿ç¨çå±é¨åéï¼å¦ææ³å®ç°çº¿ç¨é´å±é¨åéä¼ éå¯ä»¥ä½¿ç¨ InheritableThreadLocal ç±»
```java
public static void main(String[] args) {
ThreadLocal threadLocal = new InheritableThreadLocal<>();
threadLocal.set("ç¶çº¿ç¨è®¾ç½®çå¼");
new Thread(() -> System.out.println("å线ç¨è¾åºï¼" + threadLocal.get())).start();
}
// å线ç¨è¾åºï¼ç¶çº¿ç¨è®¾ç½®çå¼
```
***
##### å®ç°åç
InheritableThreadLocal æºç ï¼
```java
public class InheritableThreadLocal extends ThreadLocal {
protected T childValue(T parentValue) {
return parentValue;
}
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
```
å®ç°ç¶å线ç¨é´çå±é¨åéå
±äº«éè¦è¿½æº¯å° Thread 对象çæé æ¹æ³ï¼
```java
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,
// è¯¥åæ°é»è®¤æ¯ true
boolean inheritThreadLocals) {
// ...
Thread parent = currentThread();
// 夿ç¶çº¿ç¨ï¼å建å线ç¨ç线ç¨ï¼ç inheritableThreadLocals 屿§ä¸ä¸º null
if (inheritThreadLocals && parent.inheritableThreadLocals != null) {
// å¤å¶ç¶çº¿ç¨ç inheritableThreadLocals 屿§ï¼å®ç°ç¶å线ç¨å±é¨åéå
񄧮
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}
// ..
}
// ãæ¬è´¨ä¸è¿æ¯å建 ThreadLocalMapï¼åªæ¯æç¶ç±»ä¸çå¯ç»§æ¿æ°æ®è®¾ç½®è¿å»äºã
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
```
```java
private ThreadLocalMap(ThreadLocalMap parentMap) {
// è·åç¶çº¿ç¨çåå¸è¡¨
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new Entry[len];
// ãé个å¤å¶ç¶çº¿ç¨ ThreadLocalMap ä¸çæ°æ®ã
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
ThreadLocal