2014-09-04 55 views

回答

2

區別在於HashMap不是線程安全的,這意味着如果你有多個線程使用它,你需要自己照顧併發操作。您可以使用Collections.synchronizedMap(map)來創建一個包裝對象,其中所有方法都是​​(在該包裝對象上)並委託給包裝貼圖,從而可以很容易地使其線程安全。正如你可以看出這意味着糟糕的表現,因爲只有一個線程(讀寫器無關緊要)可以訪問它。

正如您所指出的那樣ConcurrentHashMap是線程安全的,並嘗試處理與Collections.synchronizedMap()有點不同的同步。通過將底層映射分區爲存儲桶並且每個存儲桶具有一個鎖,它將嘗試使用多個鎖來代替單個鎖。由於這些線程可以同時使用地圖而不會出現問題,因爲它們可能正在處理不同桶中的記錄。在這種情況下,您不需要鎖定整個地圖(所有存儲桶),而只需鎖定您感興趣的記錄所在的存儲桶,這意味着您可以同時對所有存儲桶執行並行操作。顯然,如果所有線程都在同一條記錄(或同一個存儲桶)上工作,它們仍會像Collections.synchronizedMap()一樣同步,並且在寫入時會被阻塞。當讀者線程數量超過編寫器線程數時,這種方法非常好。

例如,你可能有(很簡單):

ConcurrentHashMap = [ bucket1 = [r1->x], bucket2 = [r2->y], bucket3 = [r3, z] ] 

當你這樣做是爲了與主要R1條目的讀取/寫入操作的地圖會選擇bucket1作爲記錄應該有並鎖定bucket1並僅鎖定bucket1。然後,如果另一個線程如果查詢r2它可以安全地這樣做,但如果它查詢r1也必須等待bucket1被鎖定。

當然,所有這一切背後都有性能損失,但並不是很高(儘管我沒有任何基準來支持這一說法)。

這是否回答你的問題?

+0

非常好的解釋。 – Chaitanya 2014-09-04 11:16:28

0

不,在非選擇(EX。put)操作的情況下,鎖定總是在段級別進行。

您可以看到ConcurrentHashMap源代碼。

每當你在併發hashmap上調用put()方法時,它首先計算特定段的哈希位置,然後只在該段上調用trylock()方法,而不是在表級別調用。

0

ConcurentHashMap的結構與簡單的HashMap不同。 初始化時,ConcurrentHashMap被分爲多個段(默認爲16)。

它允許相似數量的線程同時訪問這些段,以便每個線程在特定段上工作。

當一個線程在一個段上工作時,它會對其進行鎖定。它不會阻止其餘的細分市場。

如果您想了解更多關於它,我建議下面的鏈接 - 有明確的例子

Link

相關問題