java面試-Java內存模型(JMM)


一、並發編程兩個關鍵問題

線程之間如何通信、同步。java並發采用的是共享內存模型

二、JMM內存模型的抽象結構
描述的是一組規則或規范,通過這組規范定義了程序中各個變量(包括實例字段,靜態字段和構成數組對象的元素)的訪問方式。

JMM決定一個線程對共享變量的寫入何時對另一個線程可見。

JMM定義了線程和主內存之間的抽象關系:線程之間的共享變量存儲在主內存(Main Memory)中,每個線程都有一個私有的本地內存(Local Memory),本地內存中存儲了該線程讀/寫共享變量的副本。

 

如果線程A與線程B之間要通信的話,必須要經歷下面2個步驟。

1)線程A把本地內存A中更新過的共享變量刷新到主內存中去。

2)線程B到主內存中去讀取線程A之前已更新過的共享變量。

 

三、JMM內存模型三大特性

1、原子性

  • AtomicInteger
  • 使用 synchronized 互斥鎖來保證操作的原子性

2、可見性:

  • volatile,會強制將該變量自己和當時其他變量的狀態都刷出緩存。
  • synchronized,對一個變量執行 unlock 操作之前,必須把變量值同步回主內存。
  • final,被 final 關鍵字修飾的字段在構造器中一旦初始化完成,並且沒有發生 this 逃逸(其它線程通過 this 引用訪問到初始化了一半的對象),那么其它線程就能看見 final 字段的值。

3、有序性

源代碼 -> 編譯器優化的重排 -> 指令並行的重排 -> 內存系統的重排 ->最終執行的命令

重排序過程不會影響到單線程程序的執行,卻會影響到多線程並發執行的正確性

處理器在進行重排時必須考慮數據的依賴性,多線程環境線程交替執行,由於編譯器優化重排的存在,兩個線程中使用的變量能否保證一致性是無法確定的。

1)編譯器優化的重排:

     編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序。

 

      

2)指令並行的重排  

      如果不存在數據依賴性,處理器可以改變語句對應機器指令的執行順序。

 

3)內存系統的重排

     由於處理器使用緩存和讀/寫緩沖區,這使得加載和存儲操作看上去可能是在亂序執行。

  • volatile 關鍵字通過添加內存屏障(Memory Barriers)的方式來禁止特定類型的處理器重排序,即重排序時不能把后面的指令放到內存屏障之前。
  • synchronized 保證每個時刻只有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM