国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

簡述Java內存模型

ACb0y / 3199人閱讀

摘要:內存模型即,簡稱,其規范了虛擬機與計算機內存時如何協同工作的,規定了一個線程如何和何時看到其他線程修改過的值,以及在必須時,如何同步訪問共享變量。內存模型要求調用棧和本地變量存放在線程棧上,對象存放在堆上。

Java內存模型即Java Memory Model,簡稱JMM,其規范了Java虛擬機與計算機內存時如何協同工作的,規定了一個線程如何和何時看到其他線程修改過的值,以及在必須時,如何同步訪問共享變量。

JVM的內存分配

在解釋Java內存模型之前,我們先了解下JVM的內存分配的幾個概念,如下圖所示,Java內存模型把內存分為兩大塊,一個是堆一個是棧。

堆heap:運行時的數據區,由垃圾回收負責,動態分配大小。存取速度較慢;

棧stack:存取速度比堆快,僅次于寄存器,數據可以共享,大小和生存期等是固定的。

Java內存模型要求調用棧和本地變量存放在線程棧上,對象存放在堆上。
一個變量也可能是指向一個對象的引用,引用這個變量是放在線程棧上,但對象本身是放在堆上的。
一個對象它可能包含方法(methodOne..),方法包含本地變量(Local variable1..),這些本地變量都仍然是放在線程棧上的,即使這些方法所屬的對象存放在堆上,一個對象的成員變量可能會隨著對象自身存放在堆上,不管這個對象是原始類型還是引用類型。
靜態成員變量跟隨著類的定義存放在堆上,存放在堆上的對象可以被所持有對這個對象引用的線程訪問。
當一個線程可以訪問一個對象時,它也可以訪問這個對象的成員變量,如果兩個線程同時調用同一個對象上的同一個方法,他們都會訪問這個對象的成員變量,但是每一個線程都擁有了成員變量的私有拷貝。

計算機硬件架構

接下來我們再來看看計算機硬件架構的圖示:

這里是個多CPU的結構,一個cpu中可能還包含多核。因此我們可以看出,在有兩個或者多個cpu的現代計算機上,同時運行多個線程是有可能的,而且每個cpu在某個時刻運行一個線程是沒問題的。若Java程序是多線程的,在Java程序中,每個cpu上一個線程是可能同時并發執行的。

在CPU內部有一組CPU寄存器,也就是CPU的儲存器。

CPU操作寄存器的速度要比操作計算機主存快的多,在主存和CPU寄存器之間還存在一個CPU緩存,CPU操作CPU緩存的速度快于主存但慢于CPU寄存器。即CPU操作的速度上主存 < 緩存 < 寄存器。某些CPU可能有多個緩存層(一級緩存和二級緩存)。計算機的主存也稱作RAM,所有的CPU都能夠訪問主存,而且主存比上面提到的緩存和寄存器大很多。

當一個CPU需要訪問主存時,會先讀取一部分主存數據到CPU緩存,進而在讀取CPU緩存到寄存器。當CPU需要寫數據到主存時,同樣會先將寄存器的數據刷新到CPU緩存,然后再在某些節點把緩存數據刷新到主存。

Java內存模型和硬件內存架構并不一致。硬件內存架構中并沒有區分棧和堆,從硬件上看,所有的線程棧和堆都分布在主主存中,當然一部分棧和堆的數據也有可能會存到CPU緩存和寄存器中,如下圖所示,Java內存模型和計算機硬件內存架構是一個交叉關系:

并發編程模型的兩個關鍵問題

在并發編程中,需要處理兩個關鍵問題:線程之間如何通信及線程之間如何同步(這里的線程是指并發執行的活動實體)。通信是指線程之間以何種機制來交換信息。在命令式編程中,線程之間的通信機制有兩種:共享內存和消息傳遞。

在共享內存的并發模型里,線程之間共享程序的公共狀態,通過寫-讀內存中的公共狀態進行隱式通信。在消息傳遞的并發模型里,線程之間沒有公共狀態,線程之間必須通過發送消息來顯式進行通信。
同步是指程序中用于控制不同線程間操作發生相對順序的機制。在共享內存并發模型里,同步是顯式進行的。程序員必須顯式指定某個方法或某段代碼需要在線程之間互斥執行。
在消息傳遞的并發模型里,由于消息的發送必須在消息的接收之前,因此同步是隱式進行的。
Java的并發采用的是共享內存模型,Java線程之間的通信總是隱式進行,整個通信過程對程序員完全透明。

Java內存模型的抽象結構

接下來我們從抽象角度看看線程和主存之間的抽象關系:

線程之間的共享變量存儲在主內存里,每個線程都有個私有的本地內存,存儲了該線程以讀/寫共享變量的副本。它涵蓋了緩存、寫緩沖區、寄存器以及其他的硬件和編譯器優化。本地內存是JMM的一個抽象概念,并不真實存在。

從上圖來看,如果線程A與線程B之間要通信的話,必須要經歷下面2個步驟。
1)線程A把本地內存A中更新過的共享變量刷新到主內存中去。
2)線程B到主內存中去讀取線程A之前已更新過的共享變量。

本地內存A和本地內存B由主內存中共享變量x的副本。假設初始時,這3個內存中的x值都為0。線程A在執行時,把更新后的x值(假設值為1)臨時存放在自己的本地內存A中。當線程A和線程B需要通信時,線程A首先會把自己本地內存中修改后的x值刷新到主內
存中,此時主內存中的x值變為了1。隨后,線程B到主內存中去讀取線程A更新后的x值,此時線程B的本地內存的x值也變為了1。
從整體來看,這兩個步驟實質上是線程A在向線程B發送消息,而且這個通信過程必須要經過主內存。JMM通過控制主內存與每個線程的本地內存之間的交互,來為Java程序員提供內存可見性保證。

Java內存模型的同步操作和規則

為了保證并發時程序處理的準確性,這里就需要一些同步的手段,這里我們介紹一下Java內存模型定義的同步的八種操作和一些規則。

八種操作

lock(鎖定):作用于主內存的變量,把一個變量標識為一條線程獨占狀態;

unlock(解鎖):作用于主內存的變量,把一個處于鎖定狀態的變量釋放出來,釋放后的變量才可以被其他線程鎖定;

read(讀取):作用于主內存的變量,把一個變量值從主內存傳輸到線程的工作內存中,以便隨后的load動作使用;

load(載入):作用于工作內存的變量,它把read操作從主內存中得到的變量值放入工作內存的變量副本中;

use(使用):作用于工作內存的變量,把工作內存中的一個變量值傳遞給執行引擎;

assign(賦值): 作用于工作內存的變量,它把一個執行引擎接受到的值賦值給工作內存的變量;

store(存儲):作用于工作內存的變量,把工作內存中的一個變量的值傳送到主內存中,以便隨后的write操作;

write(寫入): 作用于主內存的變量,他把store操作從工作內存中一個變量的值傳送到主內存的變量中。

規則

不允許read/load,store/write單一出現,且必須按順序執行,但中間可以插入其他指令;

不允許一個線程丟棄離他最近的assign操作

不允許一個線程未發生assign操作就將數據同步至主線程;

一個新的變量,只能從主內存中誕生,不允許在工作內存中生成一個未被初始化的變量。

一個變量在同一時刻只允許一個線程執行lock操作,lock可以被同一個線程執行多次,需要相同次數的unlock操作才能解鎖;

如果一個變量執行了lock操作,則會清空工作內存中的值,執行引擎使用這個變量前需要重新執行load或者assign操作來拿到初始化變量的值;

如果一個變量沒有被lock操作執行,則不允許對其進行unlock操作,也不允許unlock一個被其他線程lock的變量,unlock操作執行之前,必須將此變量同步回主內存。

參考文檔:

《Java并發編程的藝術》

https://blog.csdn.net/suifeng...

https://coding.imooc.com/lear...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69274.html

相關文章

  • JAVA9-12新特性簡述

    摘要:本文是個人在企業內部分享使用的簡要大綱,列舉了的重要更新,文章的結構較簡單,也不規范,鑒于近期寫若干文章時總會忘記一些新特性所處的版本,特將此大綱流留用。 本文是個人在企業內部分享使用的簡要大綱,列舉了JAVA9-12的重要更新,文章的結構較簡單,也不規范,鑒于近期寫若干文章時總會忘記一些新特性所處的版本,特將此大綱流copy留用。 一 JAVA9 新特性 1.Java Platfo...

    TigerChain 評論0 收藏0
  • 史上最全阿里 Java 面試題總結

    摘要:以下為大家整理了阿里巴巴史上最全的面試題,涉及大量面試知識點和相關試題。的內存結構,和比例。多線程多線程的幾種實現方式,什么是線程安全。點擊這里有一套答案版的多線程試題。線上系統突然變得異常緩慢,你如何查找問題。 以下為大家整理了阿里巴巴史上最全的 Java 面試題,涉及大量 Java 面試知識點和相關試題。 JAVA基礎 JAVA中的幾種基本數據類型是什么,各自占用多少字節。 S...

    winterdawn 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<