作用
JMM(Java Memory Model)是java內存模型。用來屏蔽不同硬件不同操作系統訪問內存的差異性,確保java程序在不同平臺上能達到一致的內存訪問效果。也就是同一個程序在不同的虛擬機上運行,得到的結果是一致的。
規范
在jmm規范中,所有的變量(不包括局部變量和方法參數)都存儲在主內存中,每個線程都有自己的工作內存,工作內存中的變量是主內存該變量的拷貝。
線程不能直接讀寫主內存,只能操作自己工作內存中的變量,然后再同步到主內存,這樣其它線程就能看到本次修改。
主內存是多個線程共享的,工作內存是線程私有的。線程間的通信必須通過主內存來完成
JMM三大特性
原子性:一個操作是不可分割,不可中斷的,一個線程在執行時不會被其它線程干擾。java提供了synchronized關鍵字來保證原子性。
可見性:一個線程修改共享變量的值,其它線程能夠立即知道。java是通過volatile關鍵字來提供可見性,另外final和synchronized關鍵字也能實現可見性。
有序性:可以使用synchronized或者volatile關鍵字保證多線程之間操作的有序性。volatile是通過內存屏障禁止指令重排序。synchronized代碼塊在多線程下是串行執行。
JMM八種內存操作
- lock(鎖定):作用于主內存中的變量,把變量標識為線程獨占的狀態。
- read(讀取):作用于主內存的變量,把變量的值從主內存傳輸到線程的工作內存中,以便下一步的load操作使用。
- load(加載):作用于工作內存的變量,把read操作主存的變量放入到工作內存的變量副本中。
- use(使用):作用于工作內存的變量,把工作內存中的變量傳輸到執行引擎,每當虛擬機遇到一個需要使用到變量的值的字節碼指令時將會執行這個操作。
- assign(賦值):作用于工作內存的變量,它把一個從執行引擎中接受到的值賦值給工作內存的變量副本中,每當虛擬機遇到一個給變量賦值的字節碼指令時將會執行這個操作。
- store(存儲):作用于工作內存的變量,它把一個從工作內存中一個變量的值傳送到主內存中,以便后續的write使用。
- write(寫入):作用于主內存中的變量,它把store操作從工作內存中得到的變量的值放入主內存的變量中。
-
unlock(解鎖):作用于主內存的變量,它把一個處于鎖定狀態的變量釋放出來,釋放后的變量才可以被其他線程鎖定。
JMM八種內存操作
happens-before原則
- 程序次序規則:在一個線程中,按照代碼的順序,前面的操作Happens-Before于后面的任意操作。
- volatile變量規則:對一個volatile變量的寫操作,Happens-Before于后續對這個變量的讀操作。
- 傳遞規則:如果A Happens-Before B,并且B Happens-Before C,則A Happens-Before C。
- 鎖定規則:對一個鎖的解鎖操作 Happens-Before于后續對這個鎖的加鎖操作。
- 線程啟動規則:如果線程A調用線程B的start()方法來啟動線程B,則start()操作Happens-Before于線程B中的任意操作。
- 線程終結規則:線程A等待線程B完成(在線程A中調用線程B的join()方法實現),當線程B完成后(線程A調用線程B的join()方法返回),則線程A能夠訪問到線程B對共享變量的操作。
- 線程中斷規則:對線程interrupt()方法的調用Happens-Before于被中斷線程的代碼檢測到中斷事件的發生。
- 對象終結原則:一個對象的初始化完成Happens-Before于它的finalize()方法的開始。