日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Java 内存模型

發布時間:2023/12/10 74 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 内存模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為了更好的理解 Java 是如何實現 按需禁用緩存和編譯優化 的,我們首先需要對 Java 的內存模型有一個初步的了解。

Java 內存模型主要由以下三部分構成:1 個主內存、n 個線程、n 個工作內存(與線程一一對應),數據就在它們三者之間來回倒騰。那么怎么倒騰呢?靠的是 Java 提供給我們的 8 個原子操作:lock、unlock、read、load、use、assign、store、write,其操作流程示意圖如下:


一個變量從主內存拷貝到工作內存,再從工作內存同步回主內存的流程為:

|主內存| -> read -> load -> |工作內存| -> use -> |Java線程| -> assign -> |工作內存| -> store -> write -> |主內存|

Java 內存模型中的 8 個原子操作

  • lock:作用于主內存,把一個變量標識為一個線程獨占狀態。
  • read:作用于主內存,把一個變量的值從主內存傳輸到線程工作內存中,供之后的 load 操作使用。
  • load:作用于工作內存,把 read 操作從主內存中得到的變量值放入工作內存的變量副本中。
  • use:作用于工作內存,把工作內存中的一個變量傳遞給執行引擎,虛擬機遇到使用變量值的字節碼指令時會執行。
  • assign:作用于工作內存,把一個從執行引擎得到的值賦給工作內存的變量,虛擬機遇到給變量賦值的字節碼指令時會執行。
  • store:作用于工作內存,把工作內存中的一個變量傳送到主內存中,供之后的 write 操作使用。
  • write:作用于主內存,把 store 操作從工作內存中得到的變量值存入主內存的變量中。
  • unlock:作用于主內存,釋放一個處于鎖定狀態的變量。

8 個原子操作的執行規則

有關變量拷貝過程的規則

  • 不允許 read 和 load,store 和 write 單獨出現
  • 不允許線程丟棄它最近的 assign 操作,即工作內存變化之后必須把該變化同步回主內存中
  • 不允許一個線程在沒有 assign 的情況下將工作內存同步回主內存中,也就是說,只有虛擬機遇到變量賦值的字節碼時才會將工作內存同步回主內存
  • 新的變量只能從主內存中誕生,即不能在工作內存中使用未被 load 和 assign 的變量,一個變量在 use 和 store 前一定先經過了 load 和 assign

有關加鎖的規則

  • 一個變量在同一時刻只允許一個線程對其進行 lock 操作,但是可以被一個線程多次 lock(鎖的可重入)
  • 對一個變量進行 lock 操作會清空這個變量在工作內存中的值,然后在執行引擎使用這個變量時,需要通過 assign 或 load 重新對這個變量進行初始化
  • 對一個變量執行 unlock 前,必須將該變量同步回主內存中,即執行 store 和 write 操作
  • 一個變量沒有被 lock,就不能被 unlock,也不能去 unlock一個被其他線程 lock 的變量

可見性問題 -> 有序性問題

通過上圖可以發現,Java 線程只能操作自己的工作內存,其對變量的所有操作(讀取、賦值等)都必須在工作內存中進行,不能直接讀寫主內存中的變量。這就有可能會導致可見性問題:

  • 因為對于主內存中的變量 A,其在不同的線程的工作內存中可能存在不同的副本 A1、A2、A3。
  • 不同線程的 read 和 load、store 和 write 不一定是連續執行的,中間可以插入其他命令。Java 只能保證 read 和 load、store 和 write 的執行對于一個線程而言是連續的,但是并不保證不同線程的 read 和 load、store 和 write 的執行是連續的,如下圖:

    假設有兩個線程 A 和 B,其中線程 A 在寫入共享變量,線程 B 要讀取共享變量,我們想讓線程 A 先完成寫入,線程 B 再完成讀取。此時即便我們是按照 “線程 A 寫入 -> 線程 B 讀取” 的順序開始執行的,真實的執行順序也可能是這樣的:storeA -> readB -> writeA -> loadB,這將導致線程 B 讀取的是變量的舊值,而非線程 A 修改過的新值。也就是說,線程 A 修改變量的執行先于線程 B 操作了,但這個操作對于線程 B 而言依舊是不可見的
    那么如何解決這個問題呢?通過上述的分析可以發現,可見性問題的本身,也是由于不同線程之間的執行順序得不到保證導致的,因此我們也可以將它的解決和有序性合并,即對 Java 一些指令的操作順序進行限制,這樣既保證了有序性,有解決了可見性。

于是乎,Java 給出了一些命令執行的順序規范,也就是大名鼎鼎 Happens-Before 規則。

總結

以上是生活随笔為你收集整理的Java 内存模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。