Java 原子操作的原理和問題

對java併發機制的底層實現原理學習了一下,有一些淺薄的收益。

第一瞭解的是:java對象在JVM中有一個java對象頭的概念,synchronized用的鎖的信息就是存在java對象頭裏面,根據其中存儲的markword的線程是否指向自己的線程來判斷是否持有當前鎖。

java對象頭的長度視圖:


32位的對象頭的mark word存儲結構的視圖:


64位的對象頭的mark word存儲結構的視圖:



我們知道java se1.6之後,引入了偏向鎖和輕量級鎖的概念,鎖一共有4種狀態:無鎖狀態,偏向鎖狀態,輕量級鎖狀態和重量級鎖狀態。

所以在不同鎖的時候。java對象頭中markword是不一樣的。

具體事例如下圖:



第二是原子操作的實現原理:

兩個概念,1,原子操作:原子操作就是在計算機這個世界中,能夠做的最小的操作了。然而這些操作基本都基於一個叫做CAS(compare and swap)的操作,

2:緩存行:緩存的最小單位。(cache line)


拋出問題:如果兩個線程對int i=1;進行i++;的操作,我們實際期望的結果是3,但是很可能出現的結果是2.

處理器保證內存操作的原子性是基於兩個機制的。

第一:通過總線程鎖保證原子性。所謂總線程鎖就是使用處理器提供的一個LOCK#信號,當一個處理器在總線上輸出此信號時,其他處理器的請求將被阻塞住。那麼該處理器可以獨佔共享內存。(缺點:總線程鎖把CPU和內存之間的通信鎖住了,這使得鎖定期間,其他處理器不能操作其他內存地址的數據,所以總線鎖定的開銷較大。)

第二:頻繁使用的內存會緩存在處理器的L1,L2和L3高速緩存裏,那麼原子操作就可以直接再處理器內部緩存中進行,並不需要聲明總線程鎖。可以通過緩存鎖來保證原子性。所謂緩存鎖是指內存區域如果被緩存在處理器的緩存行中,並且在Lock操作期間被鎖定,那麼當它執行鎖操作回寫到內存時,處理器不在主線上聲言Lock#信號,而是修改內部的內存地址,並允許它的緩存一致性機制來保證操作的原子性,因爲緩存一致性機制會阻止同時修改由兩個以上處理器緩存的內存區域數據,當其他處理器回寫已被鎖定的緩存行的數據時,會使緩存失效。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章