java并發(fā)編程的藝術(shù) -- java內(nèi)存模型

java內(nèi)存模型的抽象結(jié)構(gòu)

實例域、靜態(tài)域、數(shù)組元素存儲在堆內(nèi)存,堆內(nèi)存是線程間共享的
局部變量、方法定義參數(shù)、異常處理參數(shù)不會在線程之間共享

java memory model

線程之間的共享內(nèi)存存儲在主內(nèi)存,每個線程都會有個本地的線程副本

重排序

  1. 編譯器優(yōu)化重排序
  2. 指令級并行重排序
  3. 內(nèi)存系統(tǒng)重排序

java內(nèi)存模型之happens-before

jmm的設(shè)計

jmm把happens-before要求禁止的重排序分為了兩類:

  • 會改變程序執(zhí)行結(jié)果的重排序
  • 不會改變程序執(zhí)行結(jié)果的重排序

jmm會這兩種不同性質(zhì)的重排序采用不同策略:

  • 對于會改變程序執(zhí)行結(jié)果的重排序,jmm要求編譯器和處理器必須禁止這種重排序
  • 對于不會改變程序執(zhí)行結(jié)果的重排序,jmm沒有要求(即為許可這種重排序)

happens-before的定義

  1. 如果一個操作happens-before另一個操作,那么第一個操作的執(zhí)行結(jié)果將對第二個操作可見,而且第一個操作的執(zhí)行順序排在第二個操作之前(從編程人員角度來說:如果A happens-before B,那么java內(nèi)存模型將向程序員保證-A操作的結(jié)果將對B可見,且A的執(zhí)行順序排在B之前.注意,這只是java內(nèi)存模型像程序員做出的保證)
  2. 兩個操作之間存在happens-before關(guān)系,并不意味這java平臺的具體實現(xiàn)必須按照happens-before關(guān)系指定的順序來執(zhí)行.如果重排序之后的執(zhí)行結(jié)果,與按happens-before關(guān)系執(zhí)行的結(jié)果一致,那么是運行這種重排序(JMM其實是遵循一個基本原則:只要不改變程序的執(zhí)行結(jié)果{指的是單線程程序和正確同步的多線程程序},編譯器和處理器怎么優(yōu)化都行.JMM這么做的原因是:程序員對于這兩個操作是否真的被重排序并不關(guān)心,關(guān)心的是程序執(zhí)行時的語義不能被改變{既執(zhí)行結(jié)果不能被改變}.因此,happens-before關(guān)系本質(zhì)上和as-if-serial語義是一回事)。

happens-before規(guī)則

  1. 程序順序規(guī)則:一個線程中的每個操作,happens-before于該線程中的任意后續(xù)操作
  2. 監(jiān)視器鎖規(guī)則:對于一個鎖的解鎖,happens-before于隨后對這個鎖的加鎖
  3. volatile變量規(guī)則:對一個volatile域的寫,happens-before于任意后續(xù)對這個volatile域的讀
  4. 傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C。
  5. start()規(guī)則:如果線程A執(zhí)行操作ThreaB.start()(啟動線程B),那么A線程的 ThreaB.start()操作happens-before于線程B中的任意操作。
  6. join()規(guī)則:如果線程A執(zhí)行操作ThreaB.join()并成功返回,那么線程B中的任意操作happens-before于線程A從ThreaB.join()操作成功返回。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容