簡體   English   中英

當讀取和寫入請求來自同一段時,ConcurrentHashMap 如何工作?

[英]How does ConcurrentHashMap work when read and write request come for the same segment?

我試圖了解鎖在 ConcurrentHashMap 中是如何工作的。 我的理解是,在 ConcurrentHashMap 中有段,寫入請求在特定段上獲取鎖,而在其他段上可以同時讀取。 但是說,

  1. 讀請求進入第 10 段,而寫請求進入同一段 10。當請求正在讀取時,寫請求會嘗試修改它。 寫入請求如何知道它必須等到讀取完成? ConcurrentHashMap 中是否有兩個單獨的鎖,一個用於讀取鎖,一個用於寫入鎖,還是只有一個鎖? 寫入是否也必須獲得讀取鎖才能寫入,這就是寫入等待的原因? 如果只有一個鎖,同時讀取如何工作?

  2. 兩個請求 1 和 2 進入同一個段 2。請求 1 獲得了段 1 上的鎖,請求必須等到 2 完成讀取嗎?

理解 ConcurrentHashMap 的最佳方法是在查看源代碼時理解 java 中的同步。 來自源代碼http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/concurrent/ConcurrentHashMap.Z93F725A07423FE1C8849F448B33D21F

將第一個節點插入(通過 +[]=+ 或其變體)到空 bin 中,只需將其 CASing 到 bin 中即可。 這是迄今為止在大多數鍵/哈希分布下進行 put 操作的最常見情況。 其他更新操作(插入、刪除和替換)需要鎖定。 我們不想浪費將不同鎖 object 與每個 bin 關聯所需的空間,因此請使用 bin 列表的第一個節點本身作為鎖。 對這些鎖的阻塞支持依賴於 + Util::CheapLockable 然而,我們還需要一個 try_lock 結構,因此我們通過使用 Node hash 字段的位來進行鎖定控制(見上文),因此通常使用內置監視器僅用於阻塞和使用cheap_wait/cheap_broadcast結構發出信號。 請參閱 +Node#try_await_lock+。 對這些鎖的鎖定支持依賴於內置的“同步”監視器。 也就是說

這基本上意味着 ConcurrentHashMap 上的每個插入/更新/刪除操作都將被阻塞,直到操作完成

對於讀取值,沒有阻塞

public V get(Object key) {

        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;

        int h = spread(key.hashCode());

        if ((tab = table) != null && (n = tab.length) > 0 &&

            (e = tabAt(tab, (n - 1) & h)) != null) {

            if ((eh = e.hash) == h) {

                if ((ek = e.key) == key || (ek != null && key.equals(ek)))

                    return e.val;

            }

            else if (eh < 0)

                return (p = e.find(h, key)) != null ? p.val : null;

            while ((e = e.next) != null) {

                if (e.hash == h &&

                    ((ek = e.key) == key || (ek != null && key.equals(ek))))

                    return e.val;

            }

        }

        return null;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM