---
title: JMMï¼Java å
忍¡åï¼è¯¦è§£
description: æ·±å
¥è§£æJavaå
忍¡åJMMï¼è¯¦è§£CPUç¼å模åãæä»¤éæåºæºå¶ãhappens-beforeååãå
åå¯è§æ§ä¿è¯ï¼çè§£å¤çº¿ç¨å¹¶åç¼ç¨çåºå±è§èã
category: Java
tag:
- Javaå¹¶å
head:
- - meta
- name: keywords
content: JMM,Javaå
忍¡å,CPUç¼å,æä»¤éæåº,happens-before,å
åå¯è§æ§,å¹¶åç¼ç¨æ¨¡å
---
å¯¹äº Java æ¥è¯´ï¼ä½ å¯ä»¥æ **JMMï¼Java å
忍¡åï¼** ç使¯ Java å®ä¹çå¹¶åç¼ç¨ç¸å
³çä¸ç»è§èãé¤äºæ½è±¡äºçº¿ç¨å主å
åä¹é´çå
³ç³»ä¹å¤ï¼å
¶è¿è§å®äºä» Java æºä»£ç å° CPU 坿§è¡æä»¤ç转åè¿ç¨è¦éµå®åªäºå¹¶åç¸å
³çåååè§èãå
¶ä¸»è¦ç®çæ¯ä¸ºäº**ç®åå¤çº¿ç¨ç¼ç¨**ï¼**å¢å¼ºç¨åºçå¯ç§»æ¤æ§**ã
JMM 主è¦å®ä¹äºå¯¹äºä¸ä¸ªå
±äº«åéï¼å½ä¸ä¸ªçº¿ç¨æ§è¡åæä½åï¼è¯¥åé对å
¶ä»çº¿ç¨ç**å¯è§æ§**ã
è¦æ³éå½»çè§£ JMMï¼æä»¬éè¦ä» **CPU ç¼å模å**å**æä»¤éæåº**说起ã
## ä» CPU ç¼å模å说起
**为ä»ä¹è¦å¼ä¸ä¸ª CPU é«éç¼åå¢ï¼** ç±»æ¯æä»¬å¼åç½ç«åå°ç³»ç»ä½¿ç¨çç¼åï¼æ¯å¦ Redisï¼æ¯ä¸ºäºè§£å³ç¨åºå¤çé度å访é®å¸¸è§å
³ç³»åæ°æ®åºé度ä¸å¯¹ççé®é¢ã **CPU ç¼ååæ¯ä¸ºäºè§£å³ CPU å¤çé度åå
åå¤çé度ä¸å¯¹ççé®é¢ã**
æä»¬çè³å¯ä»¥æ **å
åçä½å¤åçé«éç¼å**ï¼ç¨åºè¿è¡çæ¶åæä»¬æå¤åçæ°æ®å¤å¶å°å
åï¼ç±äºå
åçå¤çé度è¿è¿é«äºå¤åï¼è¿æ ·æé«äºå¤çé度ã
æ»ç»ï¼**CPU Cache ç¼åçæ¯å
åæ°æ®ç¨äºè§£å³ CPU å¤çé度åå
åä¸å¹é
çé®é¢ï¼å
åç¼åçæ¯ç¡¬çæ°æ®ç¨äºè§£å³ç¡¬ç访é®éåº¦è¿æ
¢çé®é¢ã**
ä¸ºäºæ´å¥½å°çè§£ï¼æç»äºä¸ä¸ªç®åç CPU Cache 示æå¾å¦ä¸æç¤ºã
> **ð ä¿®æ£ï¼åè§ï¼[issue#1848](https://github.com/Snailclimb/JavaGuide/issues/1848)ï¼**ï¼å¯¹ CPU ç¼å模åç»å¾ä¸ä¸¥è°¨çå°æ¹è¿è¡å®åã

ç°ä»£ç CPU Cache é常å为ä¸å±ï¼åå«å« L1,L2,L3 Cacheãæäº CPU å¯è½è¿æ L4 Cacheï¼è¿éä¸å讨论ï¼å¹¶ä¸å¸¸è§
**CPU Cache ç工使¹å¼ï¼** å
å¤å¶ä¸ä»½æ°æ®å° CPU Cache ä¸ï¼å½ CPU éè¦ç¨å°çæ¶åå°±å¯ä»¥ç´æ¥ä» CPU Cache ä¸è¯»åæ°æ®ï¼å½è¿ç®å®æåï¼åå°è¿ç®å¾å°çæ°æ®åå Main Memory ä¸ã使¯ï¼è¿æ ·åå¨ **å
åç¼åä¸ä¸è´æ§çé®é¢** ï¼æ¯å¦ææ§è¡ä¸ä¸ª i++ æä½çè¯ï¼å¦æä¸¤ä¸ªçº¿ç¨åæ¶æ§è¡çè¯ï¼å设两个线ç¨ä» CPU Cache ä¸è¯»åç i=1ï¼ä¸¤ä¸ªçº¿ç¨åäº i++ è¿ç®å®ä¹åååå Main Memory ä¹å i=2ï¼èæ£ç¡®ç»æåºè¯¥æ¯ i=3ã
**CPU 为äºè§£å³å
åç¼åä¸ä¸è´æ§é®é¢å¯ä»¥éè¿å¶å®ç¼åä¸è´åè®®ï¼æ¯å¦ [MESI åè®®](https://zh.wikipedia.org/wiki/MESI%E5%8D%8F%E8%AE%AE)ï¼æè
å
¶ä»ææ®µæ¥è§£å³ã** è¿ä¸ªç¼åä¸è´æ§åè®®æçæ¯å¨ CPU é«éç¼åä¸ä¸»å
å交äºçæ¶åéè¦éµå®çåååè§èãä¸åç CPU ä¸ï¼ä½¿ç¨çç¼åä¸è´æ§åè®®é常ä¹ä¼ææä¸åã

æä»¬çç¨åºè¿è¡å¨æä½ç³»ç»ä¹ä¸ï¼æä½ç³»ç»å±è½äºåºå±ç¡¬ä»¶çæä½ç»èï¼å°åç§ç¡¬ä»¶èµæºèæåãäºæ¯ï¼æä½ç³»ç»ä¹å°±åæ ·éè¦è§£å³å
åç¼åä¸ä¸è´æ§é®é¢ã
æä½ç³»ç»éè¿ **å
忍¡åï¼Memory Modelï¼** å®ä¹ä¸ç³»åè§èæ¥è§£å³è¿ä¸ªé®é¢ãæ è®ºæ¯ Windows ç³»ç»ï¼è¿æ¯ Linux ç³»ç»ï¼å®ä»¬é½æç¹å®çå
忍¡åã
## æä»¤éæåº
说å®äº CPU ç¼å模åï¼æä»¬åæ¥ççå¦å¤ä¸ä¸ªæ¯è¾éè¦çæ¦å¿µ **æä»¤éæåº** ã
ä¸ºäºæåæ§è¡é度/æ§è½ï¼è®¡ç®æºå¨æ§è¡ç¨åºä»£ç çæ¶åï¼ä¼å¯¹æä»¤è¿è¡éæåºã
**ä»ä¹æ¯æä»¤éæåºï¼** ç®åæ¥è¯´å°±æ¯ç³»ç»å¨æ§è¡ä»£ç çæ¶åå¹¶ä¸ä¸å®æ¯æç
§ä½ åç代ç ç顺åºä¾æ¬¡æ§è¡ã
常è§çæä»¤éæåºæä¸é¢ 2 ç§æ
åµï¼
- **ç¼è¯å¨ä¼åéæ**ï¼ç¼è¯å¨ï¼å
æ¬ JVMãJIT ç¼è¯å¨çï¼å¨ä¸æ¹åå线ç¨ç¨åºè¯ä¹çåæä¸ï¼éæ°å®æè¯å¥çæ§è¡é¡ºåºã
- **æä»¤å¹¶è¡éæ**ï¼ç°ä»£å¤çå¨éç¨äºæä»¤çº§å¹¶è¡ææ¯(Instruction-Level Parallelismï¼ILP)æ¥å°å¤æ¡æä»¤éå æ§è¡ã妿ä¸å卿°æ®ä¾èµæ§ï¼å¤çå¨å¯ä»¥æ¹åè¯å¥å¯¹åºæºå¨æä»¤çæ§è¡é¡ºåºã
å¦å¤ï¼å
åç³»ç»ä¹ä¼æâéæåºâï¼ä½å䏿¯çæ£æä¹ä¸çéæåºãå¨ JMM é表ç°ä¸ºä¸»å忬å°å
åçå
容å¯è½ä¸ä¸è´ï¼è¿è导è´ç¨åºå¨å¤çº¿ç¨ä¸æ§è¡å¯è½åºç°é®é¢ã
Java æºä»£ç ä¼ç»å **ç¼è¯å¨ä¼åéæ â> æä»¤å¹¶è¡éæ â> å
åç³»ç»éæ** çè¿ç¨ï¼æç»æåææä½ç³»ç»å¯æ§è¡çæä»¤åºåã
**æä»¤éæåºå¯ä»¥ä¿è¯ä¸²è¡è¯ä¹ä¸è´ï¼ä½æ¯æ²¡æä¹å¡ä¿è¯å¤çº¿ç¨é´çè¯ä¹ä¹ä¸è´** ï¼æä»¥å¨å¤çº¿ç¨ä¸ï¼æä»¤éæåºå¯è½ä¼å¯¼è´ä¸äºé®é¢ã
对äºç¼è¯å¨ä¼åéæåå¤çå¨çæä»¤éæåºï¼æä»¤å¹¶è¡éæåå
åç³»ç»éæé½å±äºæ¯å¤çå¨çº§å«çæä»¤éæåºï¼ï¼å¤ç该é®é¢çæ¹å¼ä¸ä¸æ ·ã
- 对äºç¼è¯å¨ï¼éè¿ç¦æ¢ç¹å®ç±»åçç¼è¯å¨éæåºçæ¹å¼æ¥ç¦æ¢éæåºã
- 对äºå¤çå¨ï¼éè¿æå
¥å
åå±éï¼Memory Barrierï¼æææ¶å«åå
åæ
æ ï¼Memory Fenceï¼çæ¹å¼æ¥ç¦æ¢ç¹å®ç±»åçå¤çå¨éæåºã
> å
åå±éï¼Memory Barrierï¼æææ¶å«åå
åæ
æ ï¼Memory Fenceï¼æ¯ä¸ç§ CPU æä»¤ï¼ç¨æ¥ç¦æ¢å¤ç卿令åçéæåºï¼åå±é䏿 ·ï¼ï¼ä»èä¿éæä»¤æ§è¡çæåºæ§ãå¦å¤ï¼ä¸ºäºè¾¾å°å±éçææï¼å®ä¼å¨å¤çå¨åå
¥å¼æ¶ï¼å¼ºå¶å°åç¼å²åºä¸çæ°æ®å·æ°å°ä¸»å
åï¼å¨è¯»åå¼ä¹åï¼ä½¿å¤ç卿¬å°ç¼åä¸çç¸å
³æ°æ®å¤±æï¼å¼ºå¶ä»ä¸»å
åä¸å è½½ææ°å¼ï¼ä»èä¿éåéçå¯è§æ§ã
## JMM(Java Memory Model)
### ä»ä¹æ¯ JMMï¼ä¸ºä»ä¹éè¦ JMMï¼
Java æ¯ææ©å°è¯æä¾å
忍¡åçç¼ç¨è¯è¨ãç±äºæ©æå
忍¡ååå¨ä¸äºç¼ºé·ï¼æ¯å¦é常容æåå¼±ç¼è¯å¨çä¼åè½åï¼ï¼ä» Java5 å¼å§ï¼Java å¼å§ä½¿ç¨æ°çå
忍¡å [ãJSR-133ï¼Java Memory Model and Thread Specificationã](http://www.cs.umd.edu/~pugh/java/memoryModel/CommunityReview.pdf) ã
ä¸è¬æ¥è¯´ï¼ç¼ç¨è¯è¨ä¹å¯ä»¥ç´æ¥å¤ç¨æä½ç³»ç»å±é¢çå
忍¡åãä¸è¿ï¼ä¸åçæä½ç³»ç»å
忍¡åä¸åãå¦æç´æ¥å¤ç¨æä½ç³»ç»å±é¢çå
忍¡åï¼å°±å¯è½ä¼å¯¼è´åæ ·ä¸å¥ä»£ç æ¢äºä¸ä¸ªæä½ç³»ç»å°±æ æ³æ§è¡äºãJava è¯è¨æ¯è·¨å¹³å°çï¼å®éè¦èªå·±æä¾ä¸å¥å
忍¡å以å±è½ç³»ç»å·®å¼ã
è¿åªæ¯ JMM åå¨çå
¶ä¸ä¸ä¸ªåå ãå®é
ä¸ï¼å¯¹äº Java æ¥è¯´ï¼ä½ å¯ä»¥æ JMM ç使¯ Java å®ä¹çå¹¶åç¼ç¨ç¸å
³çä¸ç»è§èï¼é¤äºæ½è±¡äºçº¿ç¨å主å
åä¹é´çå
³ç³»ä¹å¤ï¼å
¶è¿è§å®äºä» Java æºä»£ç å° CPU 坿§è¡æä»¤çè¿ä¸ªè½¬åè¿ç¨è¦éµå®åªäºåå¹¶åç¸å
³çåååè§èï¼å
¶ä¸»è¦ç®çæ¯ä¸ºäºç®åå¤çº¿ç¨ç¼ç¨ï¼å¢å¼ºç¨åºå¯ç§»æ¤æ§çã
**为ä»ä¹è¦éµå®è¿äºå¹¶åç¸å
³çåååè§èå¢ï¼** è¿æ¯å 为并åç¼ç¨ä¸ï¼å CPU å¤çº§ç¼ååæä»¤éæè¿ç±»è®¾è®¡å¯è½ä¼å¯¼è´ç¨åºè¿è¡åºç°ä¸äºé®é¢ãå°±æ¯å¦è¯´æä»¬ä¸é¢æå°çæä»¤éæåºå°±å¯è½ä¼è®©å¤çº¿ç¨ç¨åºçæ§è¡åºç°é®é¢ï¼ä¸ºæ¤ï¼JMM æ½è±¡äº happens-before ååï¼åæä¼è¯¦ç»ä»ç»å°ï¼æ¥è§£å³è¿ä¸ªæä»¤éæåºé®é¢ã
JMM 说ç½äºå°±æ¯å®ä¹äºä¸äºè§èæ¥è§£å³è¿äºé®é¢ï¼å¼åè
å¯ä»¥å©ç¨è¿äºè§èæ´æ¹ä¾¿å°å¼åå¤çº¿ç¨ç¨åºãå¯¹äº Java å¼åè
说ï¼ä½ ä¸éè¦äºè§£åºå±åçï¼ç´æ¥ä½¿ç¨å¹¶åç¸å
³çä¸äºå
³é®ååç±»ï¼æ¯å¦ `volatile`ã`synchronized`ãåç§ `Lock`ï¼å³å¯å¼ååºå¹¶åå®å
¨çç¨åºã
### JMM æ¯å¦ä½æ½è±¡çº¿ç¨å主å
åä¹é´çå
³ç³»ï¼
**Java å
忍¡åï¼JMMï¼** æ½è±¡äºçº¿ç¨å主å
åä¹é´çå
³ç³»ï¼å°±æ¯å¦è¯´çº¿ç¨ä¹é´çå
±äº«åéå¿
é¡»åå¨å¨ä¸»å
åä¸ã
å¨ JDK1.2 ä¹åï¼Java çå
忍¡åå®ç°æ»æ¯ä» **主å** ï¼å³å
±äº«å
åï¼è¯»ååéï¼æ¯ä¸éè¦è¿è¡ç¹å«ç注æçãèå¨å½åç Java å
忍¡åä¸ï¼çº¿ç¨å¯ä»¥æåéä¿å **æ¬å°å
å** ï¼æ¯å¦æºå¨çå¯åå¨ï¼ä¸ï¼è䏿¯ç´æ¥å¨ä¸»åä¸è¿è¡è¯»åãè¿å°±å¯è½é æä¸ä¸ªçº¿ç¨å¨ä¸»åä¸ä¿®æ¹äºä¸ä¸ªåéçå¼ï¼èå¦å¤ä¸ä¸ªçº¿ç¨è¿ç»§ç»ä½¿ç¨å®å¨å¯åå¨ä¸çåéå¼çæ·è´ï¼é ææ°æ®çä¸ä¸è´ã
è¿åæä»¬ä¸é¢è®²å°ç CPU ç¼å模åé常ç¸ä¼¼ã
**ä»ä¹æ¯ä¸»å
åï¼ä»ä¹æ¯æ¬å°å
åï¼**
- **主å
å**ï¼ææçº¿ç¨å建çå®ä¾å¯¹è±¡é½åæ¾å¨ä¸»å
åä¸ï¼ä¸ç®¡è¯¥å®ä¾å¯¹è±¡æ¯æååéï¼è¿æ¯å±é¨åéï¼ç±»ä¿¡æ¯ã常éãéæåé齿¯æ¾å¨ä¸»å
åä¸ã为äºè·åæ´å¥½çè¿è¡é度ï¼èææºå硬件系ç»å¯è½ä¼è®©å·¥ä½å
åä¼å
åå¨äºå¯åå¨åé«éç¼åä¸ã
- **æ¬å°å
å**ï¼æ¯ä¸ªçº¿ç¨é½æä¸ä¸ªç§æçæ¬å°å
åï¼æ¬å°å
ååå¨äºè¯¥çº¿ç¨å·²è¯» / åå
±äº«åéç坿¬ãæ¯ä¸ªçº¿ç¨åªè½æä½èªå·±æ¬å°å
åä¸çåéï¼æ æ³ç´æ¥è®¿é®å
¶ä»çº¿ç¨çæ¬å°å
åãå¦æçº¿ç¨é´éè¦éä¿¡ï¼å¿
é¡»éè¿ä¸»å
忥è¿è¡ãæ¬å°å
忝 JMM æ½è±¡åºæ¥çä¸ä¸ªæ¦å¿µï¼å¹¶ä¸çå®åå¨ï¼å®æ¶µçäºç¼åãåç¼å²åºãå¯åå¨ä»¥åå
¶ä»ç硬件åç¼è¯å¨ä¼åã
Java å
忍¡åçæ½è±¡ç¤ºæå¾å¦ä¸ï¼

ä»ä¸å¾æ¥çï¼çº¿ç¨ 1 ä¸çº¿ç¨ 2 ä¹é´å¦æè¦è¿è¡éä¿¡çè¯ï¼å¿
é¡»è¦ç»åä¸é¢ 2 个æ¥éª¤ï¼
1. çº¿ç¨ 1 ææ¬å°å
åä¸ä¿®æ¹è¿çå
±äº«åé坿¬çå¼åæ¥å°ä¸»å
åä¸å»ã
2. çº¿ç¨ 2 å°ä¸»åä¸è¯»å对åºçå
±äº«åéçå¼ã
ä¹å°±æ¯è¯´ï¼JMM 为å
±äº«åéæä¾äºå¯è§æ§çä¿éã
ä¸è¿ï¼å¤çº¿ç¨ä¸ï¼å¯¹ä¸»å
åä¸çä¸ä¸ªå
±äº«åéè¿è¡æä½æå¯è½è¯±å线ç¨å®å
¨é®é¢ã举个ä¾åï¼
1. çº¿ç¨ 1 åçº¿ç¨ 2 åå«å¯¹åä¸ä¸ªå
±äº«åéè¿è¡æä½ï¼ä¸ä¸ªæ§è¡ä¿®æ¹ï¼ä¸ä¸ªæ§è¡è¯»åã
2. çº¿ç¨ 2 读åå°çæ¯çº¿ç¨ 1 ä¿®æ¹ä¹åçå¼è¿æ¯ä¿®æ¹åçå¼å¹¶ä¸ç¡®å®ï¼é½æå¯è½ï¼å ä¸ºçº¿ç¨ 1 åçº¿ç¨ 2 齿¯å
å°å
±äº«åéä»ä¸»å
åæ·è´å°å¯¹åºçº¿ç¨çå·¥ä½å
åä¸ã
å
³äºä¸»å
åä¸å·¥ä½å
åç´æ¥çå
·ä½äº¤äºåè®®ï¼å³ä¸ä¸ªåéå¦ä½ä»ä¸»å
åæ·è´å°å·¥ä½å
åï¼å¦ä½ä»å·¥ä½å
å忥å°ä¸»å
åä¹é´çå®ç°ç»èï¼Java å
忍¡åå®ä¹æ¥ä»¥ä¸å
«ç§åæ¥æä½ï¼äºè§£å³å¯ï¼æ éæ»è®°ç¡¬èï¼ï¼
- **éå®ï¼lockï¼**: ä½ç¨äºä¸»å
åä¸çåéï¼å°ä»æ 记为ä¸ä¸ªçº¿ç¨ç¬äº«åéã
- **è§£éï¼unlockï¼**: ä½ç¨äºä¸»å
åä¸çåéï¼è§£é¤åéçéå®ç¶æï¼è¢«è§£é¤éå®ç¶æçåéæè½è¢«å
¶ä»çº¿ç¨éå®ã
- **readï¼è¯»åï¼**ï¼ä½ç¨äºä¸»å
åçåéï¼å®æä¸ä¸ªåéçå¼ä»ä¸»å
åä¼ è¾å°çº¿ç¨çå·¥ä½å
åä¸ï¼ä»¥ä¾¿éåç load å¨ä½ä½¿ç¨ã
- **load(è½½å
¥)**ï¼æ read æä½ä»ä¸»å
åä¸å¾å°çåé弿¾å
¥å·¥ä½å
åçåéç坿¬ä¸ã
- **use(使ç¨)**ï¼æå·¥ä½å
åä¸çä¸ä¸ªåéçå¼ä¼ ç»æ§è¡å¼æï¼æ¯å½èææºéå°ä¸ä¸ªä½¿ç¨å°åéçæä»¤æ¶é½ä¼ä½¿ç¨è¯¥æä»¤ã
- **assignï¼èµå¼ï¼**ï¼ä½ç¨äºå·¥ä½å
åçåéï¼å®æä¸ä¸ªä»æ§è¡å¼ææ¥æ¶å°çå¼èµç»å·¥ä½å
åçåéï¼æ¯å½èææºéå°ä¸ä¸ªç»åéèµå¼çåèç æä»¤æ¶æ§è¡è¿ä¸ªæä½ã
- **storeï¼åå¨ï¼**ï¼ä½ç¨äºå·¥ä½å
åçåéï¼å®æå·¥ä½å
åä¸ä¸ä¸ªåéçå¼ä¼ éå°ä¸»å
åä¸ï¼ä»¥ä¾¿éåç write æä½ä½¿ç¨ã
- **writeï¼åå
¥ï¼**ï¼ä½ç¨äºä¸»å
åçåéï¼å®æ store æä½ä»å·¥ä½å
åä¸å¾å°çåéç弿¾å
¥ä¸»å
åçåéä¸ã
é¤äºè¿ 8 ç§åæ¥æä½ä¹å¤ï¼è¿è§å®äºä¸é¢è¿äºåæ¥è§åæ¥ä¿è¯è¿äºåæ¥æä½çæ£ç¡®æ§è¡ï¼äºè§£å³å¯ï¼æ éæ»è®°ç¡¬èï¼ï¼
- ä¸å
许ä¸ä¸ªçº¿ç¨æ åå å°ï¼æ²¡æåçè¿ä»»ä½ assign æä½ï¼ææ°æ®ä»çº¿ç¨çå·¥ä½å
å忥å主å
åä¸ã
- ä¸ä¸ªæ°çåéåªè½å¨ä¸»å
åä¸ âè¯çâï¼ä¸å
许å¨å·¥ä½å
åä¸ç´æ¥ä½¿ç¨ä¸ä¸ªæªè¢«åå§åï¼load æ assignï¼çåéï¼æ¢å¥è¯è¯´å°±æ¯å¯¹ä¸ä¸ªåé宿½ use å store æä½ä¹åï¼å¿
é¡»å
æ§è¡è¿äº assign å load æä½ã
- ä¸ä¸ªåéå¨åä¸ä¸ªæ¶å»åªå
è®¸ä¸æ¡çº¿ç¨å¯¹å
¶è¿è¡ lock æä½ï¼ä½ lock æä½å¯ä»¥è¢«å䏿¡çº¿ç¨é夿§è¡å¤æ¬¡ï¼å¤æ¬¡æ§è¡ lock åï¼åªææ§è¡ç¸å次æ°ç unlock æä½ï¼åéæä¼è¢«è§£éã
- 妿坹ä¸ä¸ªåéæ§è¡ lock æä½ï¼å°ä¼æ¸
空工ä½å
å䏿¤åéçå¼ï¼å¨æ§è¡å¼æä½¿ç¨è¿ä¸ªåéåï¼éè¦éæ°æ§è¡ load æ assign æä½åå§ååéçå¼ã
- 妿ä¸ä¸ªåéäºå
没æè¢« lock æä½éå®ï¼åä¸å
è®¸å¯¹å®æ§è¡ unlock æä½ï¼ä¹ä¸å
è®¸å» unlock ä¸ä¸ªè¢«å
¶ä»çº¿ç¨éå®ä½çåéã
- â¦â¦
### Java å
ååºåå JMM æä½åºå«ï¼
è¿æ¯ä¸ä¸ªæ¯è¾å¸¸è§çé®é¢ï¼å¾å¤åå¦è
éå¸¸å®¹æææ··ã **Java å
ååºååå
忍¡åæ¯å®å
¨ä¸ä¸æ ·ç两个ä¸è¥¿**ï¼
- JVM å
åç»æå Java èææºçè¿è¡æ¶åºåç¸å
³ï¼å®ä¹äº JVM å¨è¿è¡æ¶å¦ä½ååºåå¨ç¨åºæ°æ®ï¼å°±æ¯å¦è¯´å 主è¦ç¨äºåæ¾å¯¹è±¡å®ä¾ã
- Java å
忍¡åå Java çå¹¶åç¼ç¨ç¸å
³ï¼æ½è±¡äºçº¿ç¨å主å
åä¹é´çå
³ç³»å°±æ¯å¦è¯´çº¿ç¨ä¹é´çå
±äº«åéå¿
é¡»åå¨å¨ä¸»å
åä¸ï¼è§å®äºä» Java æºä»£ç å° CPU 坿§è¡æä»¤çè¿ä¸ªè½¬åè¿ç¨è¦éµå®åªäºåå¹¶åç¸å
³çåååè§èï¼å
¶ä¸»è¦ç®çæ¯ä¸ºäºç®åå¤çº¿ç¨ç¼ç¨ï¼å¢å¼ºç¨åºå¯ç§»æ¤æ§çã
### happens-before å忝ä»ä¹ï¼
happens-before è¿ä¸ªæ¦å¿µææ©è¯çäº Leslie Lamport äº 1978 å¹´å表ç论æ[ãTimeï¼Clocks and the Ordering of Events in a Distributed Systemã](https://lamport.azurewebsites.net/pubs/time-clocks.pdf)ãå¨è¿ç¯è®ºæä¸ï¼Leslie Lamport æåºäº[é»è¾æ¶é](https://writings.sh/post/logical-clocks)çæ¦å¿µï¼è¿ä¹æäºç¬¬ä¸ä¸ªé»è¾æ¶éç®æ³ ãå¨åå¸å¼ç¯å¢ä¸ï¼éè¿ä¸ç³»åè§åæ¥å®ä¹é»è¾æ¶éçååï¼ä»èè½éè¿é»è¾æ¶éæ¥å¯¹åå¸å¼ç³»ç»ä¸çäºä»¶çå
å顺åºè¿è¡å¤æã**é»è¾æ¶éå¹¶ä¸åº¦éæ¶é´æ¬èº«ï¼ä»
åºåäºä»¶åççåå顺åºï¼å
¶æ¬è´¨å°±æ¯å®ä¹äºä¸ç§ happens-before å
³ç³»ã**
ä¸é¢æå°ç happens-before è¿ä¸ªæ¦å¿µè¯ççèæ¯å¹¶ä¸æ¯éç¹ï¼ç®åäºè§£å³å¯ã
JSR 133 å¼å
¥äº happens-before è¿ä¸ªæ¦å¿µæ¥æè¿°ä¸¤ä¸ªæä½ä¹é´çå
åå¯è§æ§ã
**为ä»ä¹éè¦ happens-before ååï¼** happens-before ååçè¯çæ¯ä¸ºäºç¨åºååç¼è¯å¨ãå¤çå¨ä¹é´ç平衡ãç¨åºå追æ±çæ¯æäºçè§£åç¼ç¨ç强å
忍¡åï¼éµå®æ¢å®è§åç¼ç å³å¯ãç¼è¯å¨åå¤çå¨è¿½æ±çæ¯è¾å°çº¦æçå¼±å
忍¡åï¼è®©å®ä»¬å°½å·±æè½å°å»ä¼åæ§è½ï¼è®©æ§è½æå¤§åãhappens-before ååçè®¾è®¡ææ³å
¶å®é常ç®åï¼
- 为äºå¯¹ç¼è¯å¨åå¤çå¨ç约æå°½å¯è½å°ï¼åªè¦ä¸æ¹åç¨åºçæ§è¡ç»æï¼å线ç¨ç¨åºåæ£ç¡®æ§è¡çå¤çº¿ç¨ç¨åºï¼ï¼ç¼è¯å¨åå¤ç卿ä¹è¿è¡éæåºä¼åé½è¡ã
- 对äºä¼æ¹åç¨åºæ§è¡ç»æçéæåºï¼JMM è¦æ±ç¼è¯å¨åå¤çå¨å¿
é¡»ç¦æ¢è¿ç§éæåºã
ä¸é¢è¿å¼ æ¯ææ ¹æ® ãJava å¹¶åç¼ç¨çèºæ¯ãè¿æ¬ä¹¦ä¸çä¸å¼ JMM è®¾è®¡ææ³ç¤ºæå¾éæ°ç»å¶çã

äºè§£äº happens-before ååçè®¾è®¡ææ³ï¼æä»¬åæ¥çç JSR-133 对 happens-before ååçå®ä¹ï¼
- 妿ä¸ä¸ªæä½ happens-before å¦ä¸ä¸ªæä½ï¼é£ä¹ç¬¬ä¸ä¸ªæä½çæ§è¡ç»æå°å¯¹ç¬¬äºä¸ªæä½å¯è§ï¼å¹¶ä¸ç¬¬ä¸ä¸ªæä½çæ§è¡é¡ºåºæå¨ç¬¬äºä¸ªæä½ä¹åã
- 两个æä½ä¹é´åå¨ happens-before å
³ç³»ï¼å¹¶ä¸æå³ç Java å¹³å°çå
·ä½å®ç°å¿
é¡»è¦æç
§ happens-before å
³ç³»æå®çé¡ºåºæ¥æ§è¡ã妿éæåºä¹åçæ§è¡ç»æï¼ä¸æ happens-before å
³ç³»æ¥æ§è¡çç»æä¸è´ï¼é£ä¹ JMM ä¹å
è®¸è¿æ ·çéæåºã
æä»¬çä¸é¢è¿æ®µä»£ç ï¼
```java
int userNum = getUserNum(); // 1
int teacherNum = getTeacherNum(); // 2
int totalNum = userNum + teacherNum; // 3
```
- 1 happens-before 2
- 2 happens-before 3
- 1 happens-before 3
è½ç¶ 1 happens-before 2ï¼ä½å¯¹ 1 å 2 è¿è¡éæåºä¸ä¼å½±å代ç çæ§è¡ç»æï¼æä»¥ JMM æ¯å
许ç¼è¯å¨åå¤ç卿§è¡è¿ç§éæåºçãä½ 1 å 2 å¿
é¡»æ¯å¨ 3 æ§è¡ä¹åï¼ä¹å°±æ¯è¯´ 1,2 happens-before 3 ã
**happens-before åå表达çæä¹å
¶å®å¹¶ä¸æ¯ä¸ä¸ªæä½åçå¨å¦å¤ä¸ä¸ªæä½çåé¢ï¼è½ç¶è¿ä»ç¨åºåçè§åº¦ä¸æ¥è¯´ä¹å¹¶æ 大ç¢ãæ´åç¡®å°æ¥è¯´ï¼å®æ´æ³è¡¨è¾¾çæä¹æ¯åä¸ä¸ªæä½çç»æå¯¹äºåä¸ä¸ªæä½æ¯å¯è§çï¼æ 论è¿ä¸¤ä¸ªæä½æ¯å¦å¨åä¸ä¸ªçº¿ç¨éã**
举个ä¾åï¼æä½ 1 happens-before æä½ 2ï¼å³ä½¿æä½ 1 åæä½ 2 ä¸å¨åä¸ä¸ªçº¿ç¨å
ï¼JMM ä¹ä¼ä¿è¯æä½ 1 çç»æå¯¹æä½ 2 æ¯å¯è§çã
### happens-before 常è§è§åæåªäºï¼è°è°ä½ ççè§£ï¼
happens-before çè§åå°± 8 æ¡ï¼è¯´å¤ä¸å¤ï¼éç¹äºè§£ä¸é¢å举ç 5 æ¡å³å¯ãå
¨è®°æ¯ä¸å¯è½çï¼å¾å¿«å°±å¿è®°äºï¼æä¹ä¸å¤§ï¼éæ¶æ¥é
å³å¯ã
1. **ç¨åºé¡ºåºè§å**ï¼ä¸ä¸ªçº¿ç¨å
ï¼æç
§ä»£ç 顺åºï¼ä¹¦åå¨åé¢çæä½ happens-before äºä¹¦åå¨åé¢çæä½ï¼
2. **è§£éè§å**ï¼è§£é happens-before äºå éï¼
3. **volatile åéè§å**ï¼å¯¹ä¸ä¸ª volatile åéçåæä½ happens-before äºåé¢å¯¹è¿ä¸ª volatile åéç读æä½ã说ç½äºå°±æ¯å¯¹ volatile åéçåæä½çç»æå¯¹äºåçäºå
¶åç任使ä½é½æ¯å¯è§çã
4. **ä¼ éè§å**ï¼å¦æ A happens-before Bï¼ä¸ B happens-before Cï¼é£ä¹ A happens-before Cï¼
5. **线ç¨å¯å¨è§å**ï¼Thread 对象ç `start()`æ¹æ³ happens-before äºæ¤çº¿ç¨çæ¯ä¸ä¸ªå¨ä½ã
å¦æä¸¤ä¸ªæä½ä¸æ»¡è¶³ä¸è¿°ä»»æä¸ä¸ª happens-before è§åï¼é£ä¹è¿ä¸¤ä¸ªæä½å°±æ²¡æé¡ºåºçä¿éï¼JVM å¯ä»¥å¯¹è¿ä¸¤ä¸ªæä½è¿è¡éæåºã
### happens-before å JMM ä»ä¹å
³ç³»ï¼
happens-before ä¸ JMM çå
³ç³»å¦ä¸å¾æç¤ºï¼

- JMM åç¨åºåæä¾äº **â happens-before è§å â**ï¼å¦ç¨åºé¡ºåºè§åã`volatile` åéè§åçï¼ãè¿æ¯ä¸ç§ **â 强å
忍¡å â** çå象ï¼ç¨åºåä¸éè¦å
³å¿åºå±å¤æçéæåºç»èï¼åªéè¦æç
§è¿äºè§åç¼å代ç ï¼å°±è½ä¿è¯å¤çº¿ç¨ä¸çå
åå¯è§æ§ã
- JVM 卿§è¡æ¶ï¼ä¼å° happens-before è§åæ å°å°å
·ä½çå®ç°ä¸ã为äºå¨ä¿è¯æ£ç¡®æ§çåæä¸ä¸ä¸§å¤±æ§è½ï¼JMM åªä¼ **â ç¦æ¢å½±åæ§è¡ç»æçéæåº â**ã对äºä¸å½±ååçº¿ç¨æ§è¡ç»æçéæåºï¼JMM æ¯å
许çã
- æåºå±æ¯ç¼è¯å¨åå¤çå¨çå®ç **â éæåºè§å â**ã
æ»ç»æ¥è¯´ï¼JMM 就忝ä¸ä¸ªä¸é´å±ï¼å®åä¸éè¿ happens-before 为ç¨åºåæä¾ç®åçç¼ç¨æ¨¡åï¼åä¸éè¿ç¦æ¢ç¹å®éæåºï¼å©ç¨åºå±ç¡¬ä»¶æ§è½ãè¿ç§è®¾è®¡æ¢ä¿è¯äºå¤çº¿ç¨çå®å
¨æ§ï¼åæå¤§éåº¦éæ¾äºç¡¬ä»¶çæ§è½ã
## åçå¹¶åç¼ç¨ä¸ä¸ªéè¦ç¹æ§
### ååæ§
䏿¬¡æä½æè
夿¬¡æä½ï¼è¦ä¹ææçæä½å
¨é¨é½å¾å°æ§è¡å¹¶ä¸ä¸ä¼åå°ä»»ä½å ç´ çå¹²æ°è䏿ï¼è¦ä¹é½ä¸æ§è¡ã
å¨ Java ä¸ï¼å¯ä»¥åå©`synchronized`ãåç§ `Lock` 以ååç§ååç±»å®ç°ååæ§ã
`synchronized` ååç§ `Lock` å¯ä»¥ä¿è¯ä»»ä¸æ¶å»åªæä¸ä¸ªçº¿ç¨è®¿é®è¯¥ä»£ç åï¼å æ¤å¯ä»¥ä¿éååæ§ãåç§ååç±»æ¯å©ç¨ CAS (compare and swap) æä½ï¼å¯è½ä¹ä¼ç¨å° `volatile`æè
`final`å
³é®åï¼æ¥ä¿è¯ååæä½ã
### å¯è§æ§
å½ä¸ä¸ªçº¿ç¨å¯¹å
±äº«åéè¿è¡äºä¿®æ¹ï¼é£ä¹å¦å¤ç线ç¨é½æ¯ç«å³å¯ä»¥çå°ä¿®æ¹åçææ°å¼ã
å¨ Java ä¸ï¼å¯ä»¥åå©`synchronized`ã`volatile` 以ååç§ `Lock` å®ç°å¯è§æ§ã
妿æä»¬å°åé声æä¸º `volatile` ï¼è¿å°±æç¤º JVMï¼è¿ä¸ªå鿝å
±äº«ä¸ä¸ç¨³å®çï¼æ¯æ¬¡ä½¿ç¨å®é½å°ä¸»åä¸è¿è¡è¯»åã
### æåºæ§
ç±äºæä»¤éæåºé®é¢ï¼ä»£ç çæ§è¡é¡ºåºæªå¿
å°±æ¯ç¼åä»£ç æ¶åç顺åºã
æä»¬ä¸é¢è®²éæåºçæ¶å乿å°è¿ï¼
> **æä»¤éæåºå¯ä»¥ä¿è¯ä¸²è¡è¯ä¹ä¸è´ï¼ä½æ¯æ²¡æä¹å¡ä¿è¯å¤çº¿ç¨é´çè¯ä¹ä¹ä¸è´** ï¼æä»¥å¨å¤çº¿ç¨ä¸ï¼æä»¤éæåºå¯è½ä¼å¯¼è´ä¸äºé®é¢ã
å¨ Java ä¸ï¼`volatile` å
³é®åå¯ä»¥ç¦æ¢æä»¤è¿è¡éæåºä¼åã
## æ»ç»
- Java æ¯ææ©å°è¯æä¾å
忍¡åçè¯è¨ï¼å
¶ä¸»è¦ç®çæ¯ä¸ºäºç®åå¤çº¿ç¨ç¼ç¨ï¼å¢å¼ºç¨åºå¯ç§»æ¤æ§çã
- CPU å¯ä»¥éè¿å¶å®ç¼åä¸è´åè®®ï¼æ¯å¦ [MESI åè®®](https://zh.wikipedia.org/wiki/MESI%E5%8D%8F%E8%AE%AE)ï¼æ¥è§£å³å
åç¼åä¸ä¸è´æ§é®é¢ã
- ä¸ºäºæåæ§è¡é度/æ§è½ï¼è®¡ç®æºå¨æ§è¡ç¨åºä»£ç çæ¶åï¼ä¼å¯¹æä»¤è¿è¡éæåºã ç®åæ¥è¯´å°±æ¯ç³»ç»å¨æ§è¡ä»£ç çæ¶åå¹¶ä¸ä¸å®æ¯æç
§ä½ åç代ç ç顺åºä¾æ¬¡æ§è¡ã**æä»¤éæåºå¯ä»¥ä¿è¯ä¸²è¡è¯ä¹ä¸è´ï¼ä½æ¯æ²¡æä¹å¡ä¿è¯å¤çº¿ç¨é´çè¯ä¹ä¹ä¸è´** ï¼æä»¥å¨å¤çº¿ç¨ä¸ï¼æä»¤éæåºå¯è½ä¼å¯¼è´ä¸äºé®é¢ã
- ä½ å¯ä»¥æ JMM ç使¯ Java å®ä¹çå¹¶åç¼ç¨ç¸å
³çä¸ç»è§èï¼é¤äºæ½è±¡äºçº¿ç¨å主å
åä¹é´çå
³ç³»ä¹å¤ï¼å
¶è¿è§å®äºä» Java æºä»£ç å° CPU 坿§è¡æä»¤çè¿ä¸ªè½¬åè¿ç¨è¦éµå®åªäºåå¹¶åç¸å
³çåååè§èï¼å
¶ä¸»è¦ç®çæ¯ä¸ºäºç®åå¤çº¿ç¨ç¼ç¨ï¼å¢å¼ºç¨åºå¯ç§»æ¤æ§çã
- JSR 133 å¼å
¥äº happens-before è¿ä¸ªæ¦å¿µæ¥æè¿°ä¸¤ä¸ªæä½ä¹é´çå
åå¯è§æ§ã
## åè
- ãJava å¹¶åç¼ç¨çèºæ¯ã第ä¸ç« Java å
忍¡å
- ãæ·±å
¥æµ
åº Java å¤çº¿ç¨ãï¼