jvm Java內存模型
阿新 • • 發佈:2017-06-26
div 循環 指令重排序 model 引擎 註意 共享 文章 cnblogs 工作內存與主內存
java內存模型規定了所有變量都必須存儲在主內存中.
線程對變量的所有操作(賦值與讀取)都必須在工作內存中進行,而不能直接讀寫主內存的變量
線程間也無法直接訪問對象工作內存中的變量,而是通過主內存來進行交互(線程間變量值的傳遞需要主主內存來完成)
Volatile變量的特殊性
關鍵字volatile可以說是Java虛擬機最輕量級的同步機制
一個變量被定義為volatile,它將具備兩種特性:
1.保證變量對所有線程的“可見性”變量的改變將會同步更新到其他的擁用該變量的線程中,而普通的變量不能做到這裏點,普通變量的值在線程間傳遞均需要通過主內存來完成,需要註意的是:volatile只能保證變量的可見性,在多線程的環境中也並非是絕對安全的
2.使用volatile變量表示禁止指令重排序優化
指令重排序的解釋:http://blog.csdn.net/beiyetengqing/article/details/49580559
線程安全指標:可見性、原子性、有序性
Java內存模型是圍繞著可見性、原子性、有序性這三個特征建立 的
1.原子性(Atomicity):
由Java內存模型來保證原子性的操作有read、load、assign、use、store、write, 大致可以認為基本數據類型的訪問讀寫是具備原子性。如果需要一個更大的原子性保證,還有lock和unlock,在虛擬機中沒有直接把這兩操作給用戶使用,而是隱式的在字節 碼添加指令monitorenter和monitorenter進行操作.這兩個字節碼對象jdk代碼中就是同步塊-synchronize關鍵字
2.可見性(Visibility):
可見性是指當線程改變了共享的變量,其他線程能夠馬上知道此次的修改
2.1:volatile就驗證了這一點
2.2:synchronize也是可見性的,因為在其unlock操作之前,必須把變量值同步到主內存中
2.3 final也是有可見行.因為被final修飾的字段一旦被構造器初始化完成,並且構造器沒把this傳遞出去,那在其他線程中就能看見final字段的值(WTF?不懂)
3.有序性(Ordering):
編譯器或者運行時環境為了優化程序性能,會對代碼進行重排序.而volatile關鍵字本身就禁止指令重排序,synchronize則是由“一個變量在同一時刻只能有一個線程進行lock操作”獲得.持有同一個鎖的兩個同步塊只能串行的進行(why?)
硬件的效率與一致性
在計算機中,內存的讀寫與處理器的計算速度有幾個級的差距.這樣會嚴重影響到TPS(Transations Per Second). 所以會為每個處理器配一個高速緩存以緩和處理器的速度.而在計算機中,多個處理器共享一個內存,這個時候數據的讀寫操作將不會安全什麽是內存模型
名詞解釋:JMM(Java Memory Model),即Java內存模型 如果想要深入了解Java並發編程,必須先學習好JMM,JMM定義了jvm虛擬機在計算機內存中的工作方式工作內存與主內存
java內存模型規定了所有變量都必須存儲在主內存中.
線程對變量的所有操作(賦值與讀取)都必須在工作內存中進行,而不能直接讀寫主內存的變量
線程間也無法直接訪問對象工作內存中的變量,而是通過主內存來進行交互(線程間變量值的傳遞需要主主內存來完成)
內存間相互交互
工作內存與主內存之間有規定的協議.即一個變量如何從主內存拷貝到工作內存中,又如何從工作內存同步變量到主內存中.以下有8個操作指令: 1.lock(鎖定)作用於主內存的變量中,鎖定並讓某線程獨享 2.unlock(解鎖)作用於主內存的變量中,解鎖變量以讓其他線程訪問 3.read(讀取)作用於主內存變量中,以便工作內存下一步的load操作 4.load(載入)作用於工作內存中,載入從主內存中讀取的變量 5.use(使用)作用於工作內存中.他把工作內存中的值傳遞給執行引擎,每當虛擬機需要使用到變量值的時執行這個操作 6.assign(賦值)作用於工作內存中,他把從執行引擎中返回的最新值賦值給變量,每當虛擬機遇到一個給變量賦值的字節指令碼時執行這個操作 7.store(存儲)作用於工作內存中,它把工作內存中的值傳遞到主內存中,以便下一步的write操作 8..write(寫入)作用於主內存中,它把從store操作獲取的值更新到內存中 上述的8中基本操作必須滿足以下規則: 1.不允許read、load和store、write單獨出現 2.不允許線程對其最近的assign操作,即工作內存中的變量改變後必須同步到主內存中 3.不允許一個線程無原因的同步變量到主內存中 4.一個新的變量只能從主內存中產生.工作內存中不允許使用未被初始化(load、assign)的變量 5.變量最多只能同時被一個線程執行load操作,且可以操作任意次,相對的需要執行一樣多次的unlock操作. 6.lock操作時會清除工作內存中的變量的值.當需要讀取時再從主內存中載入 7.如果一個變量沒有進行lock操作那就不允許執行unlock操作,也不能去unlock其他線程鎖定的變量 8.在執行unlock操作前變量必須先同步到主內存中Volatile變量的特殊性
關鍵字volatile可以說是Java虛擬機最輕量級的同步機制
一個變量被定義為volatile,它將具備兩種特性:
1.保證變量對所有線程的“可見性”變量的改變將會同步更新到其他的擁用該變量的線程中,而普通的變量不能做到這裏點,普通變量的值在線程間傳遞均需要通過主內存來完成,需要註意的是:volatile只能保證變量的可見性,在多線程的環境中也並非是絕對安全的
2.使用volatile變量表示禁止指令重排序優化
指令重排序的解釋:http://blog.csdn.net/beiyetengqing/article/details/49580559
線程安全指標:可見性、原子性、有序性
Java內存模型是圍繞著可見性、原子性、有序性這三個特征建立先行發生happends-before原則
如果java內存模型中只能靠volatile和synchronize關鍵字來有序性的執行,那麽有一些操作起來就會非常頻繁,所以Java語言中有一種現行發生happens-before的原則,如下 程序次序規則:在一個線程內,按照控制流順序,控制流前面的操作先行發生於控制流後面的操作,說“控制流”是因為還要考慮到分支、循環結構 管程鎖定規則:unlock操作必須先行發生於同一個鎖的lock操作 volatile規則:變量的寫操作必須先於讀操作 線程啟動規則:thread的start()方法先於任何方法 線程終止規則:線程中的所有方法都先行與對此線程終止檢測 線程中斷規則:對線程的interrupt()方法調用先行發生於被中斷線程的代碼檢測到中斷事件的發生 對象終結規則:對象的初始化完成必須先發生於finalize()方法的開始 傳遞新:A操作先於B操作,B操作先於C操作,則A操作一定先於C操作 文章基於以下兩篇好博文 http://www.cnblogs.com/xrq730/p/4859107.html http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.htmljvm Java內存模型