JMM(Java内存模型)详解
JMM介紹
- 1.什么是JMM?
- 2.JMM的三大特性:
- 1.原子性
- 2.可見性
- 3.有序性
- 3.關于同步的規定:
- 4.解釋說明
- JMM中的八種操作:
1.什么是JMM?
? JMM 是Java內存模型( Java Memory Model),簡稱JMM。它本身只是一個抽象的概念,并不真實存在,它描述的是一種規則或規范,是和多線程相關的一組規范。通過這組規范,定義了程序中對各個變量(包括實例字段,靜態字段和構成數組對象的元素)的訪問方式。需要每個JVM 的實現都要遵守這樣的規范,有了JMM規范的保障,并發程序運行在不同的虛擬機上時,得到的程序結果才是安全可靠可信賴的。如果沒有JMM 內存模型來規范,就可能會出現,經過不同 JVM 翻譯之后,運行的結果不相同也不正確的情況。
? 計算機在執行程序時,每條指令都是在CPU中執行的。而執行指令的過程中,勢必涉及到數據的讀取和寫入。由于程序運行過程中的臨時數據是存放在主存(物理內存)當中的,這時就存在一個問題,由于CPU執行速度很快,而從內存讀取數據和向內存寫入數據的過程,跟CPU執行指令的速度比起來要慢的多(硬盤 < 內存 <緩存cache < CPU)。因此如果任何時候對數據的操作都要通過和內存的交互來進行,會大大降低指令執行的速度。因此在CPU里面就有了高速緩存。也就是當程序在運行過程中,會將運算需要的數據從主存復制一份到CPU的高速緩存當中,那么CPU進行計算時,就可以直接從它的高速緩存中讀取數據或向其寫入數據了。當運算結束之后,再將高速緩存中的數據刷新到主存當中。
JMM 抽象出主存儲器(Main Memory)和工作存儲器(Working Memory)兩種。
·主存儲器是實例對象所在的區域,所有的實例都存在于主存儲器內。比如,實例所擁有的字段即位于主存儲器內,主存儲器是所有的線程所共享的。
·工作存儲器是線程所擁有的作業區,每個線程都有其專用的工作存儲器。工作存儲器存有主存儲器中必要部分的拷貝,稱之為工作拷貝(Working Copy)。
所以,線程無法直接對主內存進行操作,此外,線程A想要和線程B通信,只能通過主存進行。
2.JMM的三大特性:
JMM的三大特性:原子性、可見性、有序性。
1.原子性
一個或多個操作,要么全部執行,要么全部不執行(執行的過程中是不會被任何因素打斷的)。
2.可見性
只要有一個線程對共享變量的值做了修改,其他線程都將馬上收到通知,立即獲得最新值。
3.有序性
? 有序性可以總結為:在本線程內觀察,所有的操作都是有序的;而在一個線程內觀察另一個線程,所有操作都是無序的。前半句指 as-if-serial 語義:線程內似表現為串行,后半句是指:“指令重排序現象”和“工作內存與主內存同步延遲現象”。處理器為了提高程序的運行效率,提高并行效率,可能會對代碼進行優化。編譯器認為,重排序后的代碼執行效率更優。這樣一來,代碼的執行順序就未必是編寫代碼時候的順序了,在多線程的情況下就可能會出錯。
? 在代碼順序結構中,我們可以直觀的指定代碼的執行順序, 即從上到下按序執行。但編譯器和CPU處理器會根據自己的決策,對代碼的執行順序進行重新排序,優化指令的執行順序,提升程序的性能和執行速度,使語句執行順序發生改變,出現重排序,但最終結果看起來沒什么變化(在單線程情況下)。
? 有序性問題 指的是在多線程的環境下,由于執行語句重排序后,重排序的這一部分沒有一起執行完,就切換到了其它線程,導致計算結果與預期不符的問題。這就是編譯器的編譯優化給并發編程帶來的程序有序性問題。
Java 語言提供了 volatile 和 synchronized 兩個關鍵字來保證線程之間操作的有序性,volatile 是因為其本身包含“禁止指令重排序”的語義,synchronized 是由“一個變量在同一個時刻只允許一條線程對其進行 lock 操作”這條規則獲得的,此規則決定了持有同一個對象鎖的兩個同步塊只能串行進入。
3.關于同步的規定:
1.線程解鎖前,必須把共享變量的值刷新回主內存。
2.線程加鎖前,必須將主內存的最新值讀取到自己的工作內存。
3.加鎖解鎖是同一把鎖。
4.解釋說明
? 在JVM中,棧負責運行(主要是方法),堆負責存儲(比如new的對象)。由于JVM運行程序的實體是線程,而每個線程在創建時,JVM都會為其創建一個工作內存(有些地方稱為??臻g),工作內存是每個線程的私有數據區域。而JAVA內存模型中規定,所有變量都存儲在主內存中,主內存是共享內存區域,所有線程都可以訪問。
? 但線程對變量的操作(讀取賦值等)必須在自己的工作內存中進行。首先要將變量從主內存拷貝到自己的工作內存空間,然后對變量進行操作,操作完成后,再將變量寫回到主內存。由于不能直接操作主內存中的變量,各個線程的工作內存中存儲著主內存中的變量副本,因此,不同的線程之間無法直接訪問對方的工作內存,線程間的通信(傳值)必須通過主內存來完成。
JMM中的八種操作:
為了支持 JMM,Java 定義了8種原子操作,用來控制主存與工作內存之間的交互:
·read 讀取:作用于主內存,將共享變量從主內存傳送到線程的工作內存中。
·load 載入:作用于工作內存,把 read 讀取的值放到工作內存中的副本變量中。
·store 存儲:作用于工作內存,把工作內存中的變量傳送到主內存中。
·write 寫入:作用于主內存,把從工作內存中 store 傳送過來的值寫到主內存的變量中。
·use 使用:作用于工作內存,把工作內存的值傳遞給執行引擎,當虛擬機遇到一個需要使用這個變量的指令時,就會執行這個動作。
·assign 賦值:作用于工作內存,把執行引擎獲取到的值賦值給工作內存中的變量,當虛擬機棧遇到給變量賦值的指令時,就執行此操作。
·lock鎖定: 作用于主內存,把變量標記為線程獨占狀態。
·unlock解鎖: 作用于主內存,它將釋放獨占狀態。
總結
以上是生活随笔為你收集整理的JMM(Java内存模型)详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统的版本概况
- 下一篇: java规则引擎_Drools规则引擎(