
ãã¡ããã
åã®ãããã¯ã§åŸããããŒå¶åŸ¡ã«é¢ããç¥è
ã¯çŽ æŽãããã§ããããŸã å€ãã®è³ªåããããŸãã ããšãã°ã
ã äºåã«ã©ã®ããã«åäœããŸããïŒã ã
ã volatile
ããã£ãã·ã¥ã®ãªã»ããã§ããããšã¯æ¬åœã§ããïŒã ã
ããªãããã®çš®é¡ã®ã¡ã¢ãªã¢ãã«ããã£ãã®ã¯ãªã ã§ããïŒã ãã¹ãŠãæ£åžžã§ãããäœããå§ãŸã£ãã®ã§ããïŒãåã®èšäºãšåæ§ã«ããã®èšäºã¯ãæåã«ãçè«äžäœãèµ·ããã¹ãããç°¡åã«èª¬æãã次ã«ãœãŒã¹ã«è¡ããããã§ã©ããªãããèŠãããšããååã«åºã¥ããŠæ§ç¯ãããŠããŸãã ãããã£ãŠãæåã®éšåã¯Javaã ãã§ãªããäž»ã«é©çšå¯èœã§ãããããä»ã®ãã©ãããã©ãŒã ã®éçºè
ã¯èªåã«ãšã£ãŠæçãªãã®ãèŠã€ããããšãã§ããŸãã
çè«çæå°å€
éã®çç£æ§ã®å¢å ã¯ãçç±ã«ããå¢å ããŠããŸãã ããšãã°ããã»ããµãéçºãããšã³ãžãã¢ã¯ãã³ãŒãããããã«æœè±¡çãªãªãŠã ãçµãããšãã§ããããŸããŸãªæé©åãèãåºããŸãã ãã ããç¡æã®ããã©ãŒãã³ã¹ã¯ãããŸããããã®å Žåãã³ãŒãã®å®è¡æ¹æ³ã®çŽæã«åããå¯èœæ§ã¯äŸ¡æ Œã§ãã æœè±¡åã«ãã£ãŠç§ãã¡ããé ãããéã®ããŸããŸãªç¹åŸŽããããããããŸãã ãŸã ãããè¡ã£ãŠããªã人ã¯ãéåããã©ãŒãã³ã¹å¹æãšåŒã°ããã»ã«ã²ã€ã»
ãŠã©ã«ã©ã¹ã»ã¯ã¯ã»ã³ã³ã®
ã¬ããŒããèªãããšããå§ãããŸãã äŸã«ã€ããŠã¯èª¬æããŸãããããã£ãã·ã¥ãèŠãŠã¿ãŸãããã
ãã£ãã·ã¥ããã€ã¹
ãã¡ã€ã³ã¡ã¢ãªãã®èŠæ±ã¯é«äŸ¡ãªæäœã§ãããææ°ã®ãã·ã³ã§ããæ°çŸããç§ãããããšããããŸãã ãã®éãããã»ããµã¯å€ãã®åœä»€ãå®äºããæéããããŸãã æ°žç¶çãªããŠã³ã¿ã€ã ãšãã圢ã§ã®æªããé¿ããããã«ããã£ãã·ã¥ã䜿çšãããŸãã ç°¡åã«èšãã°ãããã»ããµã¯ãã¡ã€ã³ã¡ã¢ãªã®é »ç¹ã«äœ¿çšãããã³ã³ãã³ãã®ã³ããŒããã®ããé£ã«ä¿åããŸãã ããŸããŸãªã¿ã€ãã®ãã£ãã·ã¥ãšãã®éå±€ã«ã€ããŠã®ããè€éãªèšèã¯
ããã«ãããŸããããã£ãã·ã¥å
ã®ããŒã¿ã®é¢é£æ§ãã©ã®ããã«ä¿èšŒããããã«ãã£ãšèå³ããããŸãã ãããŠãã·ã³ã°ã«ããã»ããµïŒãŸãã¯ã«ãŒãã«ãå°æ¥ããã»ããµãšããçšèªã䜿çšãããïŒã®å Žåãæããã«åé¡ã¯ãªãå Žåãããã€ãã®ã³ã¢
ïŒYAY MULTITHREADINGïŒïŒã§ ã質åãæ¢ã«çºçãå§ããŠããŸãã
ããã»ããµAããã£ãã·ã¥ããå Žåãããã»ããµBãäœããã®å€ãå€æŽããããšãããã»ããµAã¯ã©ã®ããã«ç¥ãããšãã§ããŸãã
ãŸãã¯ãèšãæãããšã ãã£ãã·ã¥ã®äžè²«æ§ã確ä¿ããæ¹æ³ã¯ïŒ
ããŸããŸãªããã»ããµãäžçã®äžè²«ããç¶æ³ãææ¡ããã«ã¯ãäœããã®æ¹æ³ã§çžäºã«éä¿¡ããå¿
èŠããããŸãã 圌ãããã®ã³ãã¥ãã±ãŒã·ã§ã³ã§åŸãèŠå
ã¯ãã£ãã·ã¥ã³ããŒã¬ã³ã¹ãããã³ã«ãšåŒã°ã
ãŸã ã
ãã£ãã·ã¥ã³ããŒã¬ã³ã¹ãããã³ã«
ããŸããŸãªãããã³ã«ããããéã®çç£è
ã«ãã£ãŠç°ãªãã ãã§ãªãã1ã€ã®ãã³ããŒã®ãã¬ãŒã ã¯ãŒã¯å
ã§ãåžžã«é²åããŠããŸãã ãã ãããããã³ã«ã®äžçã¯åºå€§ã§ãããã»ãšãã©ã®ãããã³ã«ã«ã¯ããã€ãã®å
±éç¹ããããŸãã äžè¬æ§ãããäœäžãããªããã
MESIãããã³ã«ãæ€èšã
ãŸã ã ãã¡ããããããšã¯æ ¹æ¬çã«ç°ãªãã¢ãããŒãããããŸããããšãã°ã
ãã£ã¬ã¯ããªããŒã¹ã§ãã ãã ãããã®èšäºã§ã¯èæ
®ãããŠããŸããã
MESIã§ã¯ããã£ãã·ã¥å
ã®åã»ã«ã¯æ¬¡ã®4ã€ã®ç¶æ
ã®ããããã«ãªããŸãã
- ç¡å¹ïŒãã£ãã·ã¥ã«å€ããããŸãã
- ãšã¯ã¹ã¯ã«ãŒã·ãïŒå€ã¯ãã®ãã£ãã·ã¥ã«ã®ã¿ããããŸã å€æŽãããŠããŸãã
- å€æŽïŒå€ã¯ãã®ããã»ããµã«ãã£ãŠå€æŽãããŠããããããŸã§ã®ãšãããã¡ã€ã³ã¡ã¢ãªã«ãä»ã®ããã»ããµã®ãã£ãã·ã¥ã«ããããŸããã
- å
±æïŒè€æ°ã®ããã»ããµã®ãã£ãã·ã¥ã«ååšããå€
ç¶æ
ããåãæ¿ããã«ã¯ãã¡ãã»ãŒãžäº€æãè¡ãããŸãããã®åœ¢åŒããããã³ã«ã®äžéšã§ãã ã¡ãªã¿ã«ããã®ãããªäœã¬ãã«ã§ã¯ãã¡ãã»ãŒãžã®äº€æã«ãã£ãŠç¶æ
ã®å€åãæ£ç¢ºã«çºçããã®ã¯ãããç®èã§ãã åé¡ã俳åªã¢ãã«å«ãïŒ
èšäºã®ãµã€ãºãçž®å°ããèªè
ãç¬èªã«åŠç¿ããããã«ä¿ãããã«ãã¡ãã»ãŒãžã³ã°ã«ã€ããŠè©³ãã説æããŸããã åžæãã人ã¯ãããšãã°ããã°ãããèšäº
Memory BarriersïŒa Hardware View for Software Hackersã§ãã®æ
å ±ãå
¥æã§ããŸãã äŒçµ±çã«ã
ãã§ã¬ãã³ããã®ãããã¯ã«é¢ããããæ·±ãèã
ã¯åœŒã®ããã°ã§èŠã€ããããš
ãã§ã
ãŸã ã
ã¡ãã»ãŒãžèªäœã®èª¬æãå·§ã¿ã«ã¹ãããããŠããããã«ã€ããŠ2ã€ã®çºèšãè¡ããŸãã ãŸããã¡ãã»ãŒãžã¯å³åº§ã«é
ä¿¡ãããªããããç¶æ
ãå€æŽããããã®åŸ
ã¡æéãçºçããŸãã 第äºã«ãäžéšã®ã¡ãã»ãŒãžã«ã¯ç¹å¥ãªåŠçãå¿
èŠã§ãããããã»ããµã®ããŠã³ã¿ã€ã ãçºçããŸãã ããã¯ãã¹ãŠãããŸããŸãªã¹ã±ãŒã©ããªãã£ãšããã©ãŒãã³ã¹ã®åé¡ã«ã€ãªãããŸãã
MESIããã³ããããåŒãèµ·ããåé¡ã®æé©å
ãããã¡ãä¿åãã
å
±æç¶æ
ã®ã¡ã¢ãªãã±ãŒã·ã§ã³ã«äœããæžã蟌ãã«ã¯ãInvalidateã¡ãã»ãŒãžãéä¿¡ããå
šå¡ã確èªããã®ãåŸ
ã€å¿
èŠããããŸãã ã¡ãã»ãŒãžãå°çããæéã¯éåžžãåçŽãªåœä»€ãå®äºããã®ã«å¿
èŠãªæéãããæ°æ¡é·ãããããã®éãããã»ããµã¯ã¢ã€ãã«ç¶æ
ã«ãªããŸããããã¯éåžžã«æ²ããããšã§ãã ãã®ãããªç¡æå³ã§å®¹èµŠã®ãªãããã»ããµãŒæéã®æ倱ãé¿ããããã«ã圌ãã¯
Store Buffersãæãã€ããŸããã ããã»ããµã¯ãæžã蟌ã¿ããå€ããã®ãããã¡ã«é
眮ããåœä»€ã®å®è¡ãç¶ããŸãã ãããŠãå¿
èŠãªInvalidate Acknowledgeãåä¿¡ããããšãããŒã¿ã¯æçµçã«ã¡ã€ã³ã¡ã¢ãªã«éä¿¡ãããŸãã
ãã¡ãããããã€ãã®æ°ŽäžçæããããŸãã ãããã®æåã®ãã®ã¯éåžžã«æçœã§ãïŒå€ããããã¡ãåºãåã«ãåãããã»ããµããããèªã¿èŸŒãããšãããšãããã¯æžãããã®ãåãåããŸããã ããã¯ã
ã¹ãã¢ãã©ã¯ãŒãã£ã³ã°ã䜿çšããŠè§£æ±ºãããŸããèŠæ±ãããå€ããããã¡å
ã«ãããã©ãããåžžã«ç¢ºèªããŸãã ããã«ããå Žåãæå³ã¯ããããåãããŸãã
ãããã2çªç®ã®ã¬ãŒãã¯ãã§ã«ã¯ããã«èå³æ·±ããã®ã§ãã ã»ã«ãã¹ãã¢ãããã¡å
ã§åãé åºã§é
眮ãããå Žåãã»ã«ãåãé åºã§æžã蟌ãŸããããšãä¿èšŒãããã®ã¯ãããŸããã 次ã®æ¬äŒŒã³ãŒããæ€èšããŠãã ããã
void executedOnCpu0() { value = 10; finished = true; } void executedOnCpu1() { while(!finished); assert value == 10; }
äœãããŸããããªãããã«æããŸããïŒ ããªããæããããããªãããšã«åããŠãããããã ããšãã°ãã³ãŒãã®å®è¡ã®éå§ãŸã§ã«Cpu0ãExclusiveç¶æ
ã«ããã
value
ãç¡å¹ãªç¶æ
ã«ããããšãå€æããå Žåã
value
ã¯bufferã
finished
ãããåŸã«æ®ããŸãã ãããŠãCpu1ã
true
ãšããŠ
finished
ãã
value
ã10ã«çãããªãå¯èœæ§ããã
value
ããã®çŸè±¡ã¯ã
䞊ã¹æ¿ããšåŒã°ããŸãã ãã¡ããã䞊ã¹æ¿ãã¯ãã®å Žåã ãã§ãªãè¡ãããŸãã ããšãã°ãã³ã³ãã€ã©ã¯ãäœããã®çç±ã§ãããã€ãã®åœä»€ã亀æããå¯èœæ§ããããŸãã
ãã¥ãŒãç¡å¹ã«ãã
ç°¡åã«æšæž¬ã§ããããã«ãã¹ãã¢ãããã¡ã¯ç¡éã§ã¯ãªãããããªãŒããŒãããŒããåŸåããããŸãããã®çµæãInvalidate AcknowledgeãåŸ
ããªããã°ãªããªãããšããããããŸãã ãŸããããã»ããµãšãã£ãã·ã¥ãããžãŒã®å Žåãéåžžã«æéããããå ŽåããããŸãã ãã®åé¡ã解決ããã«ã¯ã
Invalidate Queueãšããæ°ãããšã³ãã£ãã£ãå°å
¥ããŸãã ã¡ã¢ãªã»ã«ã®ç¡å¹åã®èŠæ±ã¯ãã¹ãŠãã®ãã¥ãŒã«å
¥ãããã確èªå¿çãå³åº§ã«éä¿¡ãããŸãã å®éãããã»ããµãŒãå¿«é©ã«åäœãããšãå€ã¯ç¡å¹ã«ãªããŸãã åæã«ãããã»ããµã¯é©åã«åäœããããšãçŽæãããã®ã»ã«ãç¡å¹ã«ãªããŸã§ã¡ãã»ãŒãžãéä¿¡ããŸããã ãã£ãããæããŸããïŒ ã³ãŒãã«æ»ããŸãããã
void executedOnCpu0() { value = 10; finished = true; } void executedOnCpu1() { while(!finished); assert value == 10; }
ç§ãã¡ã幞éã ã£ãïŒãŸãã¯ããã€ãã®ç§å¯ã®ç¥èã䜿çšããïŒãšä»®å®ããCpu0ã¯å¿
èŠãªé åºã§ã¡ã¢ãªã»ã«ãæžãçããŸããã ããã«ãããåãé åºã§Cpu1ãã£ãã·ã¥ã«èœã¡ãããšãä¿èšŒãããŸããïŒ ãã§ã«ç解ã§ããããã«ããããã ãŸãã
value
ã»ã«ãExclusiveç¶æ
ã®Cpu1ãã£ãã·ã¥ã«ãããšä»®å®ããŸãã ã¢ã¯ã·ã§ã³ã®é åºã¯æ¬¡ã®ããã«ãªããŸãã
ïŒ | Cpu0 | Cpu0ïŒå€ | CPU0ïŒçµäº | CPU1 | Cpu1ïŒå€ | CPU1ïŒçµäº |
0 | ïŒ...ïŒ | 0ïŒå
±æïŒ | falseïŒæä»çïŒ | ïŒ...ïŒ | 0ïŒå
±æïŒ | ïŒç¡å¹ïŒ |
|
1 | value = 10; - store_buffer(value) â invalidate(value) | 0ïŒå
±æïŒ ïŒã¹ãã¢ãããã¡ãŒã«10åïŒ | falseïŒæä»çïŒ |
2 | | while (!finished); â read(finished) | 0ïŒå
±æïŒ | ïŒç¡å¹ïŒ |
3 | finished = true; | 0ïŒå
±æïŒ ïŒã¹ãã¢ãããã¡ãŒã«10åïŒ | trueïŒå€æŽæžã¿ïŒ |
4 | | â invalidate(value) â invalidate_ack(value) - invalidate_queue(value) | 0ïŒå
±æïŒ ïŒç¡å¹åãã¥ãŒå
ïŒ | ïŒç¡å¹ïŒ |
5 | â read(finished) â read_resp(finished) | 0ïŒå
±æïŒ ïŒã¹ãã¢ãããã¡ãŒã«10åïŒ | trueïŒå
±æïŒ |
6 | | â read_resp(finished) | 0ïŒå
±æïŒ ïŒç¡å¹åãã¥ãŒå
ïŒ | trueïŒå
±æïŒ |
7 | | > assert value == 10; | 0ïŒå
±æïŒ ïŒç¡å¹åãã¥ãŒå
ïŒ | trueïŒå
±æïŒ |
| ã¢ãµãŒã·ã§ã³ã倱æãã |
N | | - invalidate(value) | ïŒç¡å¹ïŒ | trueïŒå
±æïŒ |
ãã«ãã¹ã¬ããã¯åçŽã§ç°¡åã§ãããïŒ åé¡ã¯ã¹ãããïŒ4ïŒ-ïŒ6ïŒã«ãããŸãã ïŒ4ïŒã§
invalidate
ãåãåã£ãã®ã§ããããå®è¡ããã®ã§ã¯ãªãããã¥ãŒã«æžã蟌ã¿ãŸãã ãããŠãã¹ãããïŒ6ïŒã§ãïŒ2ïŒãããåã«éä¿¡ããã
read
èŠæ±ã®
read_response
ãååŸããŸãã ãã ããããã¯
value
ãç¡å¹ã«ããããšã匷å¶ãããã®ã§ã¯ãªããããã¢ãµãŒã·ã§ã³ãäœäžããŸãã æäœïŒNïŒã以åã«å®è¡ãããå ŽåããŸã ãã£ã³ã¹ããããŸããããã®ããŸããŸããæé©åã¯ãã¹ãŠãå£ããŠããŸããŸããïŒ ããããäžæ¹ã§ã圌女ã¯ãšãŠãéããç§ãã¡ã«è¶
äœé
延â¢ãæäŸããŸãïŒ ããããžã¬ã³ãã§ãã éã®éçºè
ã¯ãæé©åã®äœ¿çšããã€èš±å¯ããããã€ãããäœããå£ãå¯èœæ§ãããã®ãââãéæ³ã®ããã«äºåã«ç¥ãããšã¯ã§ããŸããã ãããŠã圌ãã¯åé¡ãç§ãã¡ã«äŒãããäžäººã§è¡ãã®ã¯å±éºã§ãã ãããæã£ãŠïŒã
ããŒããŠã§ã¢ã¡ã¢ãªã¢ãã«
ãã©ãŽã³ãšæŠãããã«è¡ã£ãéçºè
ã«ãã£ãŠæäŸãããéæ³ã®å£ã¯ãå®éã«ã¯ãŸã£ããå£ã§ã¯ãªããã²ãŒã ã®ã«ãŒã«ã§ãã ãããã¯ãããã»ããµãŸãã¯å¥ã®ããã»ããµãç¹å®ã®ã¢ã¯ã·ã§ã³ãå®è¡ãããšãã«ããã»ããµãèŠãããšãã§ããå€ãèšè¿°ããŸãã ããããã¡ã¢ãªãŒããªã¢ã¯ãã§ã«å£ã®ãããªãã®ã§ãã æ€èšããŠããMESIã®äŸã§ã¯ã次ã®ãããªå£ããããŸãã
ã¹ãã¢ã¡ã¢ãªããªã¢ ïŒSTãSMBãsmp_wmbãïŒ-ãã®åœä»€ã®åŸã«ç¶ãã¹ãã¢ãå®è¡ããåã«ãæ¢ã«ãããã¡å
ã«ãããã¹ãŠã®ã¹ãã¢ãããã»ããµã«å®è¡ãããåœä»€
Load Memory Barrier ïŒLDãRMBãsmp_rmbïŒ-ããã»ããµã«ãããŒãåœä»€ãå®è¡ããåã«ãã¥ãŒå
ã®ãã¹ãŠã®ç¡å¹åã匷å¶çã«é©çšããåœä»€
æ°ããæŠåšãèªç±ã«äœ¿çšã§ããã®ã§ãç°¡åã«äŸãä¿®æ£ã§ããŸãã
void executedOnCpu0() { value = 10; storeMemoryBarrier(); finished = true; } void executedOnCpu1() { while(!finished); loadMemoryBarrier(); assert value == 10; }
çŽ æŽãããããã¹ãŠãæ©èœããæºè¶³ããŠããŸãïŒ ã¯ãŒã«ã§çç£çã§æ£ãããã«ãã¹ã¬ããã³ãŒããäœæã§ããŸãã åæ¢ããŸãã...
Javaã¯ã©ãã«ããã®ã§ããããïŒ
äžåºŠæžãã ãã§ã©ãã§ãå®è¡
çè«çã«ã¯ããããã®ããŸããŸãªãã£ãã·ã¥ã³ããŒã¬ã³ã¹ãããã³ã«ãèããã©ãã·ã¥ããããã£ãã·ã¥ãããã³ãã®ä»ã®ãã©ãããã©ãŒã åºæã®ãã®ã¯ãã¹ãŠãJavaã³ãŒããæžã人ãå¿é
ããã¹ãã§ã¯ãããŸããã Javaã¯ãã©ãããã©ãŒã ã«äŸåããŸããããïŒ å®éãJava Memory Modelã«ã¯äžŠã¹æ¿ãã®æŠå¿µã¯ãããŸããã
NB ïŒãã®ãã¬ãŒãºãããªããæ··ä¹±ããããªãããã®çç±ãç解ãããŸã§èšäºãèªã¿ç¶ããªãã§ãã ããã ãããŠãäŸãã°ã ãããèªãã§ãã ãã ã
äžè¬çã«ãé¢çœãã§ããã ã䞊ã¹æ¿ããã®æŠå¿µã¯ãããŸãããã䞊ã¹æ¿ãèªäœã¯ããã§ãã åœå±ã¯æããã«äœããé ããŠããŸãïŒ ããããåšå²ã®çŸå®ã®é°è¬è©äŸ¡ãæŸæ£ãããšããŠããç§ãã¡ã¯å¥œå¥å¿ãšç¥ããããšãã欲æ±ã®ãŸãŸã§ãã æ¶ããŸãããïŒ æè¿ã®äŸã瀺ãç°¡åãªã¯ã©ã¹ãèŠãŠã¿ãŸãããïŒ
[ github ] public class TestSubject { private volatile boolean finished; private int value = 0; void executedOnCpu0() { value = 10; finished = true; } void executedOnCpu1() { while(!finished); assert value == 10; } }
äŒçµ±çã«ãããã§äœãèµ·ãã£ãŠããããç¥ãããã®ããã€ãã®ã¢ãããŒãããããŸãã
PrintAssembly
ã楜ãã
PrintAssembly
ãã€ã³ã¿ãŒããªã¿ãŒã®æ©èœã確èªã
PrintAssembly
ãæ¢ã«ç¥ã£ãŠãã人ããç§å¯ã®ç¥èãçµãåºãããã§ããŸãã
äžæè°ãªè¡šæ
ã§ããã£ãã·ã¥ãããã«æšãŠãããŠèœã¡çããŠãããš
èšãããšãã§ã
ãŸã ã
åå
ã¯ãå®éã«ã¯éçšç°å¢ã§ã¯
䜿çšãããªãã€ã³ã¿ãŒããªã¿ãŒãèŠãŸããã ä»åã¯ãã¯ã©ã€ã¢ã³ãã³ã³ãã€ã©ïŒC1ïŒã®åäœãèŠãŠãããŸãã ç§ã¯ç®çã®ããã«
openjdk-7u40-fcs-src-b43-26_aug_2013ã䜿çšããŸããã
OpenJDKã®ãœãŒã¹ã³ãŒãã以åã«éããŠããªã人ïŒããã³ãããéãã人ïŒã«ãšã£ãŠãå¿
èŠãªã¢ã¯ã·ã§ã³ãã©ãã§å®è¡ãããŠããããèŠã€ããã®ã¯å°é£ãªäœæ¥ã«ãªãå¯èœæ§ããããŸãã ãããè¡ãæãç°¡åãªæ¹æ³ã®1ã€ã¯ããã€ãã³ãŒãã調ã¹ãŠç®çã®åœä»€ã®ååãèŠã€ãããããæ€çŽ¢ããããšã§ãã
$ javac TestSubject.java && javap -c TestSubject void executedOnCpu0(); Code: 0: aload_0
泚æ ïŒãã€ãã³ãŒãã䜿çšããŠãå®è¡æã®ããã°ã©ã ã®æ£ç¢ºãªåäœã決å®ããããšããªãã§ãã ããã JITã³ã³ãã€ã©ãŒããã®ä»äºãããåŸããã¹ãŠã倧ããå€ããå¯èœæ§ããããŸãã
ããã§ã©ããªé¢çœãããšãããããŸããïŒ å€ãã®äººãå¿ããŠããæåã®å°ããªããšã¯ãã¢ãµãŒã·ã§ã³ãããã©ã«ãã§ãªãã«ãªã£ãŠããããšã§ãã
-ea
ã䜿çšããŠã
-ea
æå¹ã«ããããšãã§ã
-ea
ã ããããããã¯ããããã³ã»ã³ã¹ã§ãã ããã«æ¥ãã®ã¯
getfield
ãš
putfield
ååã§ãã ç§ã話ããŠããã®ãšåãããšã ãšæããŸããïŒ
ïŒãã¡ãããGlebïŒããŒã³ã³ããã©ã³ãžã£ãŒã 2ã€ã®ãã©ãžã£ãŒããDyson Sphereãã©ã®ããã«æ§ç¯ããã®ã§ããïŒ!!ïŒãŠãµã®ã®ç©Žãäžã
åãåœä»€ãäž¡æ¹ã®ãã£ãŒã«ãã«äœ¿çšãããããšã«æ³šæããŠããã£ãŒã«ãã
volatile
ã§ãããšããæ
å ±ãã©ãã«å«ãŸããŠãããèŠãŠã¿ãŸãããã ã¯ã©ã¹
share/vm/ci/ciField.hpp
ãã£ãŒã«ãããŒã¿ãæ ŒçŽããããã«äœ¿çšãããŸãã æ¹æ³ã«èå³ããããŸã
176 | bool is_volatile () { return flags().is_volatile(); } |
volatile
ãã£ãŒã«ããžã®ã¢ã¯ã»ã¹ã§C1ãäœããããã調ã¹ãããã«ããã®ã¡ãœããã®ãã¹ãŠã®äœ¿çšæ³ãèŠã€ããããšãã§ããŸãã ãã³ãžã§ã³ãå°ã
share/vm/c1/c1_LIRGenerator.cpp
ãå€ä»£ã®ç¥èãæã€ããã€ãã®å·»ç©ãåéããåŸããã¡ã€ã«
share/vm/c1/c1_LIRGenerator.cpp
èªåèªèº«ãèŠã€ããŸãã 圌ã®ååã瀺åããããã«ã圌ã¯ç§ãã¡ã®ã³ãŒãã®äœã¬ãã«äžéè¡šçŸïŒ
LIR ãäœã¬ãã«äžéè¡šçŸïŒãçæããŠããŸãã
äŸãšããŠputfield
ã䜿çšããC1äžéè¡šçŸ
C1ã§IRãäœæãããšãããã§
putfield
åœä»€ãæçµçã«åŠçãããŸãã
volatile
ãã£ãŒã«ãã«å¯ŸããŠå®è¡ãããç¹å¥ãªã¢ã¯ã·ã§ã³ãæ€èšããããã«äœ¿ãæ
£ããèšèã«åºããããŸãã
1734 1735 1736 | if (is_volatile && os::is_MP()) { __ membar_release(); } |
ããã§
__
ã¯
gen()->lir()->
å±éããããã¯ãã§ãã ãããŠã
membar_release
ã¡ãœãã
membar_release
share/vm/c1/c1_LIR.hpp
å®çŸ©ãããŠã
share/vm/c1/c1_LIR.hpp
ïŒ
1958 | void membar_release() { append(new LIR_Op0(lir_membar_release)); } |
å®éããã®è¡ã¯ãmembar_releaseã¹ããŒãã¡ã³ããã³ãŒãã®äžéè¡šçŸã«è¿œå ããŸããã ãã®åŸã次ã®ããšãçºçããŸãã
1747 1748 1749 | if (is_volatile && !needs_patching) { volatile_field_store(value.result(), address, info); } |
volatile_field_store
ã®å®è£
volatile_field_store
ãã§ã«ãã©ãããã©ãŒã ã«äŸåããŠããŸãã ããšãã°ãx86ïŒ
cpu/x86/vm/c1_LIRGenerator_x86.cpp
ïŒã§ã¯ãã¢ã¯ã·ã§ã³ã¯éåžžã«ç°¡åã§ãããã£ãŒã«ãã64ããããã©ããããã§ãã¯ããããã§ããã°ãBlack Magicã䜿çšããŠèšé²ã®ååæ§ãä¿èšŒããŸãã
volatile
ãªãå Žåã
long
åãš
double
åã®ãã£ãŒã«ãã¯
éååçã«èšè¿°ã§ããããšããŸã èŠããŠããŸããïŒ
ãããŠæåŸã«ãæåŸã«å¥ã®membarãé
眮ãããŸããä»åã¯ãªãªãŒã¹ãªãã§ãã
1759 1760 1761 | if (is_volatile && os::is_MP()) { __ membar(); } |
1956 | void membar() { append(new LIR_Op0(lir_membar)); } |
NB ïŒãã¡ãããç§ã¯ç¥ãã¬éã«é²è¡äžã®æŽ»åã®ããã€ããé ããŸããã ããšãã°ãGCã«é¢é£ããæäœã èªè
ã¯ç¬ç«ããæŒç¿ãšããŠããããç 究ããããã«æåŸ
ãããŠããŸãã
IRãã¢ã»ã³ãã©ãŒã«å€æ
STãšLDã®ã¿ãééããŸããããããã«ã¯æ°ããã¿ã€ãã®éå£ããããŸãã å®éã以åèŠããã®ã¯äœã¬ãã«ã®MESIã®éå£ã®äžäŸã§ãã ãããŠããã§ã«ããé«ãã¬ãã«ã®æœè±¡åã«ç§»è¡ããŠãããçšèªã¯å€å°å€æŽãããŠããŸãã ã¹ãã¢ãšããŒãã®2çš®é¡ã®ã¡ã¢ãªæäœããããšããŸãã 次ã«ãããŒããšããŒããããŒããšã¹ãã¢ãã¹ãã¢ãšããŒããã¹ãã¢ãšã¹ãã¢ã®2ã€ã®æäœã®4ã€ã®é åºä»ãçµã¿åããããããŸãã
StoreStoreãš
LoadLoadã® 2ã€ã®ã«ããŽãªã調æ»ããŸãã
-MESIã«ã€ããŠè©±ããŠãããšãã«èŠãã®ãšåãéå£ããããŸãã ä»ã®2ã€ãéåžžã«ç°¡åã«æ¶åã§ããã¯ãã§ãã
LoadStoreã®åã«çæããããã¹ãŠã®ããŒãã¯ãã¹ãã¢ã®åã«å®äºããå¿
èŠããããŸãã
StoreLoadã®å Žå ãããããéã
trueã§ãã ããã«ã€ããŠã¯ãããšãã°
JSR-133 Cookbookã§è©³ããèªãããšãã§ããŸãã
ããã«ã
Acquireã»ãã³ãã£ã¯ã¹ã䜿çšããæäœãš
Releaseã»ãã³ãã£ã¯ã¹ã䜿çšããæäœã®æŠå¿µã¯åºå¥ãããŸãã åŸè
ã¯æžã蟌ã¿æäœã«é©çšå¯èœã§ããããã®æäœã®åã«å®è¡ãããã¡ã¢ãªæäœã¯ãéå§ããåã«å®äºããå¿
èŠããããŸãã èšãæãããšãæžã蟌ã¿ãšè§£æŸã®ã»ãã³ãã£ã¯ã¹ã䜿çšããæäœã¯ãããã°ã©ã ããã¹ãå
ã§ãã®åã«ããã¡ã¢ãªã䜿çšããæäœã§äžŠã¹æ¿ããããšã¯ã§ããŸããã LoadStore + StoreStoreã¡ã¢ãªããªã¢ã®çµã¿åããã«ããããã®ãããªã»ãã³ãã£ã¯ã¹ãæäŸã§ããŸãã ãæ³åã®ãšãããAcquireã¯å察ã®ã»ãã³ãã£ã¯ã¹ãæã¡ãLoadStore + LoadLoadã®çµã¿åããã䜿çšããŠè¡šçŸã§ããŸãã
ããã§ãJVMãé
眮ããèãããããŸããã ãã ããLIRã§ã®ã¿èŠãŸããããäœã¬ãã«ã§ã¯ãããŸãããJITãçæãããã€ãã£ãã³ãŒãã§ã¯ãããŸããã C1ãLIRããã€ãã£ãã³ãŒãã«æ£ç¢ºã«å€æããæ¹æ³ã®ç 究ã¯ãã®èšäºã®ç¯å²ãè¶
ããŠããããããã以äžèŠåŽããããšãªãããã¡ã€ã«
share/vm/c1/c1_LIRAssembler.cpp
ãŸãã ããã§ãIRããã¢ã»ã³ãã©ãŒã³ãŒããžã®å€æããã¹ãŠè¡ãããŸãã ããšãã°ãéåžžã«äžåãªè¡ã§
lir_membar_release
ã
lir_membar_release
èæ
®ãããŸãã
665 666 667 | case lir_membar_release: membar_release(); break; |
åŒã³åºãããã¡ãœããã¯ãã§ã«ãã©ãããã©ãŒã ã«äŸåããŠãããx86ã®ãœãŒã¹ã³ãŒãã¯
cpu/x86/vm/c1_LIRAssembler_x86.cpp
ãŸãã
3733 3734 3735 3736 | void LIR_Assembler::membar_release() { |
ãããïŒ å³å¯ãªã¡ã¢ãªã¢ãã«ïŒTSO-Total Store Orderãå«ãïŒã®ãããã§ããã®ã¢ãŒããã¯ãã£ã§ã¯ãã¹ãŠã®ã¬ã³ãŒãã«æ¢ã«ãªãªãŒã¹ã»ãã³ãã£ã¯ã¹ããããŸãã ãããã2çªç®ã®membarã§ã¯ããã¹ãŠãå°ãè€éã§ãïŒ
3723 3724 3725 3726 | void LIR_Assembler::membar() { |
ããã§
__
ãã¯ãã¯
_masm->
ã«å±éããã
membar
ã¡ãœããã¯
cpu/x86/vm/assembler_x86.hpp
ããã次ã®ããã«ãªããŸãã
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | void membar(Membar_mask_bits order_constraint) { if (os::is_MP()) { |
x86ã§ã¯ãå
volatile
å€æ°ã®ã¬ã³ãŒãã«
lock addl $0x0,(%rsp)
ã®åœ¢åŒã§é«äŸ¡ãªStoreLoadããªã¢ãé
眮ããããšãããããŸããã
ãã®æäœã¯ããããã¡å
ã®ãã¹ãŠã®ã¹ãã¢ã匷å¶çã«å®è¡ãããããè²»çšãããããŸããããããããã¯ç§ãã¡ãæåŸ
ããã®ãšåãå¹æãäžããŸãvolatile
-ä»ã®ãã¹ãŠã®ã¹ã¬ããã¯ãå°ãªããšããã®å®è¡æã«é¢é£ããŠããå€ãèŠãã§ããããx86ã§ã®èªã¿åããæãäžè¬çãªèªã¿åãã§ããããšãå€æããŸãããã¡ãœãããç°¡åã«èª¿ã¹ããšãLIRGenerator::do_LoadField
äºæ³ãããšãããèªã¿åãåŸã«membar_acquireãèšå®ãããŠããããšãããããŸããx86ã§ã¯æ¬¡ã®ããã«ãªããŸãã 3728 3729 3730 3731 | void LIR_Assembler::membar_acquire() { |
ãã¡ãããããã¯ãŸã volatile read
éåžžã®ãªãŒããŒããããšæ¯èŒããŠãªãŒããŒããããçºçããªãããšãæå³ããŸããread
ãããšãã°ããã€ãã£ãã³ãŒãã«ã¯äœãè¿œå ãããŸããããIRèªäœã«ããªã¢ããããããã³ã³ãã€ã©ã¯ç¹å®ã®åœä»€ãåé
眮ã§ããŸãããïŒããã§ãªããã°ãé¢çœããã°ããã£ããã§ããŸãïŒãvolatileã䜿çšãããšãä»ã«ãå€ãã®å¹æããããŸããããã«ã€ããŠã¯ãããšãã°ãã®èšäºã§èªãããšãã§ããŸããã·ã©ãã®ç¢ºèª
ããªã³ãã¢ãã»ã³ããªãŒ
ãœãŒã¹ã«åº§ã£ãŠæšæž¬ããããšã¯ãèªå°å¿ã®ããå²åŠè
ã«ãµããããé«è²Žãªè·æ¥ã§ãããã ãã念ã®ããããŸã ãèŠãŠãã ããPrintAssembly
ããããè¡ãã«ã¯ãã«ãŒãå
ã®å®éšãŠãµã®ã®å¿
èŠãªã¡ãœããã«å€ãã®åŒã³åºããè¿œå ããã€ã³ã©ã€ã³åããªãã«ããŠïŒçæãããã³ãŒãå
ãããã²ãŒãããããããããïŒãã¢ãµãŒã·ã§ã³ããªã³ã«ããããšãå¿ããã«ã¯ã©ã€ã¢ã³ãVMã§éå§ããŸãã $ java -client -ea -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:MaxInlineSize=0 TestSubject ... # {method} 'executedOnCpu0' '()V' in 'TestSubject' ... 0x00007f6d1d07405c: movl $0xa,0xc(%rsi) 0x00007f6d1d074063: movb $0x1,0x10(%rsi) 0x00007f6d1d074067: lock addl $0x0,(%rsp) ;*putfield finished ; - TestSubject::executedOnCpu0@8 (line 15) ... # {method} 'executedOnCpu1' '()V' in 'TestSubject' ... 0x00007f6d1d061126: movzbl 0x10(%rbx),%r11d ;*getfield finished ; - TestSubject::executedOnCpu1@1 (line 19) 0x00007f6d1d06112b: test %r11d,%r11d ...
ããã¯çŽ æŽãããããã¹ãŠãç§ãã¡ãäºæž¬ãããšããã«èŠããŸããäžåšã®å Žåvolatile
ãäœããæ¬åœã«ããŸããããªããã©ããã確èªããããšã¯æ®ã£ãŠããŸããèšäºã®ååã§ãTheShadeã¯å£ããDouble-Checked Lockingã瀺ããŸããããå°ãæªæ²ãããã®ã§ãèªåã§ãã¹ãŠãå£ãããšããŸãããŸãããŸãã¯ã»ãšãã©ããªãèªèº«ãæ®çºæ§ã®ãªãé害ã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³
ãã®ãããªåã¬ã³ããªã³ã°ãå®èšŒããåé¡ã¯ãäžè¬çãªã±ãŒã¹ã§ã®ãã®çºçã®å¯èœæ§ãããã»ã©é«ããªãããšã§ãããåã
ã®HMMã¢ãŒããã¯ãã£ã§ã¯ãŸã£ããèš±å¯ãããŸããããããã£ãŠãã¢ã«ãã¡ãååŸããããã³ã³ãã€ã©ã§ã®åã¬ã³ããªã³ã°ã«äŸåããå¿
èŠããããŸããããã«ããã¹ãŠãäœåºŠãäœåºŠãå®è¡ããŸãããã®ããã«èªè»¢è»ãçºæããå¿
èŠããªãã®ã¯è¯ãããšã§ããçŽ æŽãããjstressãŠãŒãã£ãªãã£ã䜿çšããŸããç°¡åã«èšãã°ãããã€ãã®ã³ãŒããç¹°ãè¿ãå®è¡ããå®è¡çµæã®çµ±èšãåéããŠããã¹ãŠã®æ±ãä»äºãããŠãããŸããå€ãã®äººãçãããããªãå¿
èŠæ§ã«ã€ããŠã®ãã®ãå«ããããã«ãå¿
èŠãªãã¹ãã¯ãã§ã«æžãããŠããŸããããæ£ç¢ºã«ã¯ãããå°ãè€éã§ãããäœãèµ·ãã£ãŠããããå®å
šã«ç€ºããŠããŸãïŒ static class State { int x; int y;
2ã€ã®ã¹ã¬ããããããŸãã1ã€ã¯ç¶æ
ãå€æŽãã2ã€ç®ã¯ç¶æ
ãèªã¿åãããã®çµæãä¿åããŸãããã¬ãŒã ã¯ãŒã¯ã¯çµæãéèšããããã€ãã®ã«ãŒã«ã«åŸã£ãŠçµæããã§ãã¯ããŸãã 2çªç®ã®ã¹ããªãŒã ãèŠãããšãã§ãã2ã€ã®çµæã«èå³ããããŸãïŒ[1, 0]
ãš[1, 1]
ããããã®ã±ãŒã¹ã§ã¯ãæã
ã¯èªãã§y == 1
ãç§ãã¡ã¯ã©ã¡ããã®ã¬ã³ãŒãã®ä»»æã®äžŠã¹æ¿ã衚瀺ãããŠããªãx
ïŒãx == 0
ïŒãŸãã¯ææ°ã®èšé²æã«ã¯èŠãŠããªãy
ã§ããx == 1
ãç§ãã¡ã®çè«ã«ãããšããã®ãããªçµæãçããã¯ãã§ããããã確èªããŠãã ããïŒ $ java -jar tests-all/target/jcstress.jar -v -t ".*UnfencedAcquireReleaseTest.*" ... Observed state Occurrence Expectation Interpretation [0, 0] 32725135 ACCEPTABLE Before observing releasing write to, any value is OK for $x. [0, 1] 15 ACCEPTABLE Before observing releasing write to, any value is OK for $x. [0, 2] 36 ACCEPTABLE Before observing releasing write to, any value is OK for $x. [0, 3] 10902 ACCEPTABLE Before observing releasing write to, any value is OK for $x. [1, 0] 65960 ACCEPTABLE_INTERESTING Can read the default or old value for $x after $y is observed. [1, 3] 50929785 ACCEPTABLE Can see a released value of $x if $y is observed. [1, 2] 7 ACCEPTABLE Can see a released value of $x if $y is observed.
ããã§ã¯ã83731840ã®ãã¡65960件ïŒçŽ0.07ïŒ
ïŒã®ã±ãŒã¹y == 1 && x == 0
ã§ãåçºçãæ確ã«èªãããŠããããšãããããŸããããããããèªè
ã¯ãèšäºã®åé ã§å°ãããã質åã«çããããã«äœãèµ·ãã£ãŠããã®ããååã«ç解ããŠããã¯ãã§ããæãåºãããŠãã ããïŒ- ä»äºåã®ä»çµã¿ã¯ïŒ
volatile
ããããã£ãã·ã¥ããã©ãã·ã¥ããŠããã®ã¯æ¬åœã§ããïŒ- ãªãããçš®ã®ã¡ã¢ãªã¢ãã«ããã£ãã®ã§ããïŒ
ããŠããã¹ãŠãæå®ã®äœçœ®ã«èœã¡ãŸãããïŒããã§ãªãå Žåã¯ãèšäºã®é©åãªã»ã¯ã·ã§ã³ãããäžåºŠæãäžããŠã¿ãŠãã ãããããã§è§£æ±ºããªãå Žåã¯ãã³ã¡ã³ããæè¿ããŸãïŒãããŠããäžã€Â©
ããŒããŠã§ã¢ã ãã§ãªããã©ã³ã¿ã€ã ç°å¢å
šäœããœãŒã¹ã³ãŒãã®å€æãå®è¡ã§ããŸãã JMMèŠä»¶ã«æºæ ããããã«ãäœããå€æŽãããå¯èœæ§ããããã¹ãŠã®ã³ã³ããŒãã³ãã«å¶éã課ãããŸããããšãã°ãäžè¬çãªå Žåãã³ã³ãã€ã©ã¯äžéšã®åœä»€ãåé
眮ã§ããå ŽåããããŸãããJMMã®å®è¡ããå€ãã®æé©åãçŠæ¢ãããå ŽåããããŸãããã¡ããããµãŒããŒã³ã³ãã€ã©ïŒC2ïŒã¯ç§ãã¡ã調ã¹ãC1ãããããªãè³¢ãããã®äžã®ããã€ãã¯éåžžã«ç°ãªã£ãŠããŸããããšãã°ãã¡ã¢ãªãæäœããã»ãã³ãã£ã¯ã¹ã¯ãŸã£ããç°ãªããŸããOpenJDKãã«ãã¹ã¬ããã®ã¬ããã¯å€ãã®å Žæã§ãã§ãã¯ã䜿çšããŸãos::is_MP()
ããã«ãããããã€ãã®æäœãå®è¡ããããšãªããã·ã³ã°ã«ããã»ããµãã·ã³ã®ããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸããForbidden Artsã䜿çšããŠãèµ·åæã«JVMã1ã€ã®ããã»ããµã§å®è¡ãããŠãããšå€æããããã«åŒ·å¶ããå ŽåãJVMã¯é·ãåç¶ããŸãããåºçåã«èšäºãèªãã§ãããåæ¢ãªTheShadeãchereminãartyushovã«æè¬ããŸãã