java內存模型

java內存模型

一、堆Heap、棧stack

  1. Java把內存劃分成兩種:一種是棧內存,一種是堆內存。
    堆內存:主要存儲new創建的對象(類實例)和數組,由Java虛擬機(JVM)的垃圾回收器來管理。
    棧內存:函數中定義的基本類型變量和對象的引用變量。
    在堆中創建一個後,還可在棧中定義一個特殊的變量,這個變量的值=對象或數組在堆內存中的首地址,這個變量也就是我們常說的數組或對象的引用變量,以後就可以在程序中使用棧內存中的引用變量來訪問堆中數據。如果數組和對象沒有引用變量指向便不能再被使用,相當於垃圾但是仍然佔着內存(也是java比較佔內存的主要原因),在隨後的一個不確定的時間會被垃圾回收器釋放掉。棧中的變量指向堆內存中的變量,這就是 Java 中的指針!可以這麼理解,堆主要用來存放數據,棧主要是用來執行程序。
  2. 堆特點:它能動態分配內存的大小,分配的內存不需要代碼進行顯示的釋放,垃圾回收器會處理,生存期也不必事先告訴編譯器(因爲是運行時動態分配內存),但由於要在運行時動態分配內存,則存取速度較慢。
    棧特點:存取速度比堆要快,僅次於寄存器,棧數據可以共享。但棧中的數據大小和生存期必須是確定的,缺乏靈活性。
  3. JVM是基於堆棧的虛擬機,主要管理兩種類型內存:堆和非堆。
    堆內存:在 Java 虛擬機啓動時創建。儲存前面所說的對象和數組,是一個運行時數據區。
    非堆內存:在JVM堆之外的內存,簡單來說包含方法區、每個類結構(如運行時常數池、字段和方法數據)以及方法和構造方法的代碼、JVM內部處理或優化所需的內存。

二、涉及多線程編程

  1. 內存模型相關概念
    計算機在執行程序時每條指令都是在cpu中執行,而執行指令大都就涉及數據讀取修改寫入,臨時數據,而程序運行過程中臨時數據存放於主存(物理內存),而cpu執行速度很快,而從內存的讀取速度不會那麼快,那麼如果涉及到數據操作都要與主存進行交互就會大大降低指令執行速度,於是就有了高速緩存。程序運行時,會將需要運算的數據從主存複製一份到高速緩存進行計算,結束後再將高速緩存中的數據刷新到主存中。
    比如 i = i + 1;
    當線程執行這個語句時,會先從主存當中讀取i的值,然後複製一份到高速緩存當中,然後CPU執行指令對i進行加1操作,然後將數據寫入高速緩存,最後將高速緩存中i最新的值刷新到主存當中。這個在單線程中運行是沒有任何問題的,但是在多線程中運行就會有問題了。在多核CPU中,每條線程可能運行於不同的CPU中,因此每個線程運行時有自己的高速緩存(對單核CPU來說也會出現這種問題)。
    假設同時有2個線程執行這段代碼,i初始值爲0我們希望兩個線程執行完之後i的值變爲2。而不盡然,可能會出現這種情況:兩個線程分別讀取i的值存入各自所在的CPU的高速緩存當中,然後線程1進行加1操作,然後把i的最新值1寫入到內存。而此時線程2的高速緩存當中i的值還是0,進行加1操作之後,i的值爲1,然後線程2把i的值寫入內存。所以最終結果i=1,而不是2。這就是著名的緩存一致性問題。通常稱這種被多個線程訪問的變量爲共享變量。
    也就是說,如果一個變量在多個CPU中都存在緩存(一般在多線程編程時纔會出現),那麼就可能存在緩存不一致的問題。在硬件層面上有提供以下兩種方式來解決
    1.通過在總線加LOCK#鎖的方式
    2.通過緩存一致性協議,比如Intel 的MESI協議
  2. java內存模型給多線程編程的一些保證
    上面說了一些關於內存模型以及併發編程中可能會出現的一些問題。下面就來看一下Java內存模型。
    在Java虛擬機規範中試圖定義一種Java內存模型(Java Memory Model,JMM)來屏蔽各個硬件平臺和操作系統的內存訪問差異,以實現讓Java程序在各種平臺下都能達到一致的內存訪問效果。Java內存模型規定所有的變量都是存在主存當中(類似於前面說的物理內存),每個線程都有自己的工作內存(類似於前面的高速緩存)。線程對變量的所有操作都必須在工作內存中進行,而不能直接對主存進行操作。並且每個線程不能訪問其他線程的工作內存,則也會存在緩存一致性問題。
    那麼Java內存模型是如何解決這些問題,它又爲多線程編程要注意的三條特性提供了哪些保證呢。
    1.java中只對基本數據類型的變量讀取和賦值(侷限於i = 1這種形式,變量之間的賦值不算)具有原子性。
    2.java提供了synchonized和Lock可以確保原子性,可見性,有序性
    3.java還提供了volatile關鍵字確保變量的可見性,也保證了一定“有序性”,意思是說,volatile修飾的變量之前的指令肯定先於它被執行,而它之後的指令肯定會後於它執行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章