[英]Modifying values in ConcurrentHashMap
在 ConcurrentHashMap 中有分段的概念。 這意味着如果兩個線程試圖訪問 ConcurrentHashMap,它們會被分成兩個塊,塊的默認大小為 16。
現在假設在 ConcurrentHashMap 只有兩個元素和兩個不同的線程的情況下,線程 1 嘗試修改第一個值,線程 2 嘗試修改第二個值。 在這種情況下,ConcurrentHashMap 是否會進行分段?
現在在不同的場景中,兩個線程都嘗試修改相同的值 ConcurrentHashMap 將如何處理這種情況? 通過使用鎖定機制還是有別的什么?
ConcurrentHashMap 有幾個桶。 鍵根據其散列值映射到其中一個桶中。 當您添加或檢索一個值時,與該鍵關聯的存儲桶將被鎖定。
在您的第一個問題的情況下,有兩種可能性:兩個鍵都位於同一個存儲桶中,或者它們位於不同的存儲桶中。 在第一種情況下,一次只有一個線程可以工作——第一個獲取鎖的線程將獲取鎖並工作,第二個線程將等待輪到它。 在第二種情況下,密鑰位於不同的存儲桶中,它們每個都將獲得獨立的鎖並同時執行它們的工作。
對於你的第二個問題,是桶被鎖定了,沒有別的。 如果兩個線程嘗試為同一個鍵存儲兩個值,則 ConcurrentHashMap 承諾兩個值之一將與鍵相關聯。 即如果線程 A 運行map.put("Answers",2);
線程 B 運行map.put("Answers",10);
,然后 ConcurrentHashMap 將確保映射是有效的,並且包含2
或10
的"Answers"
,但它不會對這兩個中的哪一個做出任何承諾。
CHM 保證這些操作(例如put
、 putIfAbsent
等)不會重疊,是的,這是通過鎖定完成的。 CHM 的每個段都有自己的鎖,每當您修改該段時都會使用該鎖。
(作為參考,正如@Affe 指出的那樣,如果您正在修改ConcurrentHashMap
中某個值的內容,則 CHM 不會做 - 不能做 - 任何使該線程安全的事情。)
首先,新的 CHM 實現根本不使用 Segments,它仍然使用節點數組,如果給定索引中的節點不存在並且兩個線程試圖插入兩個具有等於給定索引的哈希碼的條目,則 CHM使用 CAS ,否則如果節點存在,則 CHM 使用鎖定該節點的第一個元素來放置新值。 CHM 中的讀取是非阻塞的,並且在 Unsafe 類的原子讀取的幫助下,使用發生在保證之前。 查看我關於 CHM 的博客了解更多詳情https://strogiyotec.github.io/pages/posts/chm.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.