理解Java內存模型的概念及原理,對於使用Java語言開發的工做者來講相當重要,對實際項目開發也有促進做用,也時常做爲面試題出如今各大互聯網公司的面試環節。本篇簡要介紹了Java內存模型關鍵部份內容,結合原理圖具體說明。深刻理解Java內存模型細節推薦閱讀《深刻理解Java虛擬機》第12章,本文主要原理內容說明也來自於此。面試
簡單來講是一片共享的內存區域。計算機的處理器老是併發的執行多任務,在執行任務期間處理器會與主內存進行交互,如讀取數據、存儲運算結果等。緩存
內存與處理器之間的緩衝。因爲計算機的存儲設備(IO操做)與處理器的運算速度有幾個數量級的差距,因此現代計算機系統引入一層讀寫速度儘量接近處理器運算速度的高速緩存(Cache)來做爲內存與處理器之間的緩衝:將運算須要使用到的數據複製到緩存中,讓運算速度能快速進行,當運算結束背後再從緩存同步回主內存中,這樣處理器舊無需等待緩慢的內存讀寫了。微信
當多個處理器的運算任務都涉及同一主內存時,可能出現各自的緩存數據不一致,而最終同步到主內存以哪一個緩存數據爲準。緩存一致性協議主要是約定了讀寫數據操做的協議,根據協議最終能保證數據一致性。併發
處理器、高速緩存、主內存間的交互關係: 優化
Java內存模型規定了全部的變量都存儲在主內存(Main Memory)中(此處的主內存與介紹物理硬件時的主內存名字同樣,二者也能夠相互類比,但此處僅是虛擬機內存的一部分)。每條線程還有本身的工做內存(Working Memory,可與前面講的處理器高速緩存類比),線程的工做內存保存了該線程使用到的變量的主內存拷貝副本,線程對變量的全部操做(讀取、賦值等)都必須在工做內存中進行,而不能直接讀寫主內存中的變量。不一樣的線程之間也沒法直接訪問對方工做內存中的變量,線程間變量值的傳遞均須要經過主內存來完成,線程、主內存、工做內存三者的關係圖: 線程
事實上並不會如此,這個對象的引用、對象中某個在線程訪問到的字段是有可能存在拷貝的,但不會有虛擬機實現成把整個對象拷貝一次。cdn
Java內存模型定義的8種操做:(均是原子的吧,不可再分的,可是對於double和long類型的變量來講,load、store、read和write操做在某些平臺上容許有例外)對象
經過上面的內存交互規則,若是要把一個變量從主內存複製到工做內存, 就須要順序的執行read和load操做,而若是要把一個變量從工做內存同步回主內存,則須要順序執行store和write操做,注意是順序執行,而不是連續執行,也就是兩個操做之間能夠插入其餘操做。除此以外,Java內存模型對這8中操做進行操做的其餘約束:blog
關於內存交互操做的流程簡圖:排序
volatile變量具有兩種特性:
保證變量對全部線程的可見性,這裏的「可見性」是指當一個線程修改了這個變量值,新值對於其餘線程來講是能夠當即獲得的。
禁止指令重排序優化
關於volatile變量,除了理解可見性以及指令重排,理解原子性有序性以及volatile對於long和dounble型變量的特殊規則,先行發生原則也相當重要,因爲篇幅關係本文再也不深刻介紹。
關於Java內存模型,能夠先從硬件處理器執行背景進行介紹,結合硬件的效率與一致性問題,延伸到虛擬機的Java內存模型約定的概念,如主內存工做內存,內存間交互操做進行說明,更進一步對volatile關鍵字的理解,可見性,原子性,有序性,指令重排,先行發生等等層層遞進。