繁体   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