想要了解java鎖機(jī)制、引發(fā)的線程安全問題以及數(shù)據(jù)一致性問題,有必要了解內(nèi)存模型,機(jī)理機(jī)制了解清楚了,這些問題也就應(yīng)聲而解了。
一、主內(nèi)存和工作內(nèi)存
Java內(nèi)存模型分為主內(nèi)存和工作內(nèi)存,所有的變量都存儲在主內(nèi)存中。每條線程還有自己的工作內(nèi)存,線程的工作內(nèi)存中保存了被該線程使用到變量的主內(nèi)存副本拷貝,線程對變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存中的變量。不同的線程之間也無法直接訪問對方工作內(nèi)存中的變量,線程間變量值的傳遞均需要主內(nèi)存來完成。
二、線程、工作內(nèi)存和主內(nèi)存
下面是java的內(nèi)存模型,(參見與java虛擬機(jī))

實際上,不同平臺間的處理器架構(gòu)將直接影響內(nèi)存模型的結(jié)構(gòu)。
在C或C++中, 可以利用不同操作平臺下的內(nèi)存模型來編寫并發(fā)程序. 但是, 這帶給開發(fā)人員的是, 更高的學(xué)習(xí)成本.相比之下, java利用了自身虛擬機(jī)的優(yōu)勢, 使內(nèi)存模型不束縛于具體的處理器架構(gòu), 真正實現(xiàn)了跨平臺。(針對hotspot jvm, jrockit等不同的jvm, 內(nèi)存模型也會不相同)
內(nèi)存模型的特征:
a, Visibility 可見性 (多核,多線程間數(shù)據(jù)的共享)
b, Ordering 有序性 (對內(nèi)存進(jìn)行的操作應(yīng)該是有序的)
在jmm中, 通過并發(fā)線程修改變量值, 必須將線程變量同步回主存后, 其他線程才能訪問到.來體現(xiàn)可視性(Visibility) 。通過java提供的同步機(jī)制或volatile關(guān)鍵字, 來保證內(nèi)存的訪問順序.
三、內(nèi)存間交互操作
Java內(nèi)存間操作包括8種操作:
① Lock
作用于主內(nèi)存的變量,把一個變量標(biāo)識為一個線程獨占的狀態(tài);
② Unlock
作用于主內(nèi)存的變量,把一個處于鎖定狀態(tài)的變量釋放出來;
③ Read
作用于主內(nèi)存的變量,把一個變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load的動作使用;
④ Load
作用于工作內(nèi)存中的變量,把read的操作從主內(nèi)存得到的變量值放入到工作內(nèi)存的變量的副本中;
⑤ Use
作用于工作內(nèi)存中的變量,把工作內(nèi)存中的變量傳遞給執(zhí)行引擎;
⑥ Assign
作用于工作內(nèi)存中的變量,把從執(zhí)行引擎?zhèn)鹘邮盏降淖兞抠x值給工作內(nèi)存中的變量;
⑦ Store
作用于工作內(nèi)存中的變量,把工作內(nèi)存中的變量傳送給主內(nèi)存中;
⑧ Write
作用于主內(nèi)存中的變量,把store操作的變量值放入主內(nèi)存的變量中。
上述操作中還要滿足如下原則:
1) Read和load,以及store和write不能單獨出現(xiàn);
2) Assign不能丟棄;
3) 不允許沒有assign操作的變量從線程的工作內(nèi)存中同步到主內(nèi)存;
4) Use和store的操作前必須assign和load;
5) Lock和unlock成對出現(xiàn),對象才會解鎖;
6) 沒有lock的對象不能unlock;
7) 執(zhí)行Lock操作的時候,將會清空工作內(nèi)存中此變量的值;
8) 執(zhí)行unlock之前,必須把此對象同步到主內(nèi)存中。
上面的論述初看起來有點迷糊,可以對照著模型圖進(jìn)行思考,就一目了然了。
新聞熱點
疑難解答