1. 程式人生 > >concurrenthashmap的size方法原理

concurrenthashmap的size方法原理

同上,這也是同一個面試的時候別人問的,我只是記得看過,在concurrenthashmap中會統計多次,當時就說會統計兩次進行比較,人家接著問為啥。。。我傻了一下,這不是明擺著兩次統計的中間有新的變化了,會導致統計不準確嗎?當時也不知道說啥好,以為他有新的點,就說不知道。面試時很多問題其實冷靜下來想一下,可以更進一步的,有時候其實也是怕他更進一步後下面的挖坑挖大了。

下面具體說一下這個size方法:
程式碼就不貼了。只說原理。

眾所周知,concurrenthashmap有很多歌segments,首先遍歷segments將每個segment的count加起來作為整個concurrenthashMap的size。如果沒有併發的情況下這自然就可以了,但這是多執行緒的,如果前腳統計完後腳有變化了,這就不準確了,原始碼中引入了,modCount和兩次比較來實現size的確認。具體過程是:

1.進行第一遍遍歷segments陣列,將每個segemnt的count加起來作為總數,期間把每個segment的modCount加起來sum作為結果是否被修改的判斷依據。
這裡需要提一下modCount,這個是當segment有任何操作都會進行一次增量操作,代表的是對Segment中元素的數量造成影響的操作的次數,這個值只增不減!!!!只增不減很重要,這樣就不會出現一個segment+1,導致modcount+1,而另一個segment-1,即modcount-1 ,從而在統計所有的時候modcount沒有變化。

2.size操作就是遍歷了兩次所有的Segments,每次記錄Segment的modCount值,然後將兩次的modCount進行比較,如果相同,則表示期間沒有發生過寫入操作,就將原先遍歷的結果返回,如果不相同,則把這個過程再重複做一次,如果再不相同,則就需要將所有的Segment都鎖住,然後一個一個遍歷了。

3.如果經判斷髮現兩次統計出的modCount並不一致,那就如上所說,要重新啟用全部segment加鎖的方式來進行count的獲取和統計了,這樣在此期間每個segement都被鎖住,無法進行其他操作,統計出的count自然很準確。

而之所以之所以要先不加鎖進行判斷,道理很明顯,就是不希望因為size操作獲取這麼多鎖,因為獲取鎖不光佔用資源,也會影響其他執行緒對ConcurrentHash的使用,影響併發情況下程式執行的效率。使用鎖要謹慎!

原理大概就是這樣的,具體的程式碼可以去看原始碼,而且原始碼1.7和1.8有差別。。。有空再貼出來比較比較吧。