--- title: JMMï¼Java å 忍¡åï¼è¯¦è§£ category: Java tag: - Javaå¹¶å head: - - meta - name: keywords content: CPU ç¼å模å,æä»¤éæåº,Java å 忍¡åï¼JMMï¼,happens-before - - meta - name: description content: å¯¹äº Java æ¥è¯´ï¼ä½ å¯ä»¥æ JMM ç使¯ Java å®ä¹çå¹¶åç¼ç¨ç¸å ³çä¸ç»è§èï¼é¤äºæ½è±¡äºçº¿ç¨å主å åä¹é´çå ³ç³»ä¹å¤ï¼å ¶è¿è§å®äºä» Java æºä»£ç å° CPU 坿§è¡æä»¤çè¿ä¸ªè½¬åè¿ç¨è¦éµå®åªäºåå¹¶åç¸å ³çåååè§èï¼å ¶ä¸»è¦ç®çæ¯ä¸ºäºç®åå¤çº¿ç¨ç¼ç¨ï¼å¢å¼ºç¨åºå¯ç§»æ¤æ§çã --- JMM(Javaå 忍¡å)主è¦å®ä¹äºå¯¹äºä¸ä¸ªå ±äº«åéï¼å½å¦ä¸ä¸ªçº¿ç¨å¯¹è¿ä¸ªå ±äº«åéæ§è¡åæä½åï¼è¿ä¸ªçº¿ç¨å¯¹è¿ä¸ªå ±äº«åéçå¯è§æ§ã è¦æ³çè§£éå½» JMMï¼Java å 忍¡åï¼ï¼æä»¬å è¦ä» **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ï¼ä¸¤ä¸ªçº¿ç¨åäº 1++ è¿ç®å®ä¹åååå 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 çå ³ç³»ç¨ãJava å¹¶åç¼ç¨çèºæ¯ãè¿æ¬ä¹¦ä¸çä¸å¼ å¾å°±å¯ä»¥é常好çè§£éæ¸ æ¥ã  ## åçå¹¶åç¼ç¨ä¸ä¸ªéè¦ç¹æ§ ### ååæ§ 䏿¬¡æä½æè 夿¬¡æä½ï¼è¦ä¹ææçæä½å ¨é¨é½å¾å°æ§è¡å¹¶ä¸ä¸ä¼åå°ä»»ä½å ç´ çå¹²æ°è䏿ï¼è¦ä¹é½ä¸æ§è¡ã å¨ 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 å¤çº¿ç¨ãï¼http://concurrent.redspider.group/RedSpider.html - Java å å访é®éæåºçç ç©¶ï¼https://tech.meituan.com/2014/09/23/java-memory-reordering.html - å¿ï¼åå¦ï¼ä½ è¦ç Java å 忍¡å (JMM) æ¥äºï¼https://xie.infoq.cn/article/739920a92d0d27e2053174ef2 - JSR 133 (Java Memory Model) FAQï¼https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html