happens-before规则和指令重排
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 《JAVA并發(fā)編程實戰(zhàn)》閱讀筆記1
一、 指令重排
指令重排序
Java 語言規(guī)范規(guī)定了JVM線程內(nèi)部維持順序化語義,也就是說只要程序的最終結(jié)果等同于它在嚴格的順序化環(huán)境下的結(jié)果,那么指令的執(zhí)行順序就可能 與代碼的順序不一致。這個過程通過叫做指令的重排序。指令重排序存在的意義在于:JVM能夠根據(jù)處理器的特性(CPU的多級緩存系統(tǒng)、多核處理器等)適當 的重新排序機器指令,使機器指令更符合CPU的執(zhí)行特點,最大限度的發(fā)揮機器的性能。
重排序的背景
我們知道現(xiàn)代CPU的主頻越來越高,與cache的交互次數(shù)也越來越多。當CPU的計算速度遠遠超過訪問cache時,會產(chǎn)生cache wait,過多的cache ?wait就會造成性能瓶頸。
針對這種情況,多數(shù)架構(gòu)(包括X86)采用了一種將cache分片的解決方案,即將一塊cache劃分成互不關(guān)聯(lián)地多個 slots (邏輯存儲單元,又名?Memory Bank?或 Cache Bank),CPU可以自行選擇在多個 idle bank 中進行存取。這種?SMP?的設(shè)計,顯著提高了CPU的并行處理能力,也回避了cache訪問瓶頸。
Memory Bank的劃分
一般 Memory bank 是按cache address來劃分的。比如 偶數(shù)adress 0×12345000?分到 bank 0, 奇數(shù)address 0×12345100?分到 bank1。
重排序的種類
編譯期重排。編譯源代碼時,編譯器依據(jù)對上下文的分析,對指令進行重排序,以之更適合于CPU的并行執(zhí)行。
運行期重排,CPU在執(zhí)行過程中,動態(tài)分析依賴部件的效能,對指令做重排序優(yōu)化。
二、 happens-before規(guī)則
Java存儲模型有一個happens-before原則,就是如果動作B要看到動作A的執(zhí)行結(jié)果(無論A/B是否在同一個線程里面執(zhí)行),那么A/B就需要滿足happens-before關(guān)系。
(1)同一個線程中的每個Action都happens-before于出現(xiàn)在其后的任何一個Action。
(2)對一個監(jiān)視器的解鎖happens-before于每一個后續(xù)對同一個監(jiān)視器的加鎖。
(3)對volatile字段的寫入操作happens-before于每一個后續(xù)的同一個字段的讀操作。
(4)Thread.start()的調(diào)用會happens-before于啟動線程里面的動作。
(5)Thread中的所有動作都happens-before于其他線程檢查到此線程結(jié)束或者Thread.join()中返回或者Thread.isAlive()==false。
(6)一個線程A調(diào)用另一個另一個線程B的interrupt()都happens-before于線程A發(fā)現(xiàn)B被A中斷(B拋出異?;蛘逜檢測到B的isInterrupted()或者interrupted())。
(7)一個對象構(gòu)造函數(shù)的結(jié)束happens-before與該對象的finalizer的開始
(8)如果A動作happens-before于B動作,而B動作happens-before與C動作,那么A動作happens-before于C動作。
三、 理解
而指令重排序又會對沒有依賴的兩個操作進行重排序,這不是相互矛盾的么? ? ? ?經(jīng)過網(wǎng)上翻閱了一些資料以后,我的理解是,happens-before規(guī)則是用來判斷一個動作對另一個動作是否可見的法則,他只是用來判斷可見性的,而不是決定執(zhí)行順序的,就是說動作A和動作B 的執(zhí)行順序是可以通過指令重排發(fā)生變化的,而如果你要保證A和B的可見性關(guān)系,就必須采用其他控制手段來保證AB的執(zhí)行順序不被打亂,這樣就能用happens-before規(guī)則來判斷AB兩個動作的可見性。? 參考信息: http://www.infoq.com/cn/articles/java-memory-model-2?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk http://www.blogjava.net/xylz/archive/2010/07/03/325168.html
轉(zhuǎn)載于:https://www.cnblogs.com/vipper/p/3307991.html
總結(jié)
以上是生活随笔為你收集整理的happens-before规则和指令重排的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步一步深入spring(6)--使用基
- 下一篇: 视觉库—OpenCV