微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

同一个segment的读写请求,ConcurrentHashMap是如何工作的?

如何解决同一个segment的读写请求,ConcurrentHashMap是如何工作的?

我试图了解锁在 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.java

将第一个节点插入(通过 +[]=+ 或其变体) bin 是通过将其 CASing 到 bin 来执行的。这是迄今为止最 大多数键/哈希分布下放置操作的常见情况。 其他更新操作(插入、删除和替换)需要锁定。 我们不想浪费关联不同的空间所需的空间 用每个 bin 锁定对象,所以改为使用 bin 列表的第一个节点 本身就是一把锁。对这些锁的阻塞支持依赖于 +Util::CheapLockable。但是,我们还需要一个 try_lock 构造,因此我们通过使用 Node 哈希字段的位来锁定这些位 控制(见上文),因此通常仅将内置监视器用于 使用 cheap_wait/cheap_broadcast 进行阻塞和信令 建筑。参见 +Node#try_await_lock+。锁定支持这些 锁依赖于内置的“同步”监视器。这意味着

这基本上意味着 ConcurrentHashMap 上的每个 Insert/Update/Delete 操作都会被阻塞,直到操作完成

对于读取值没有阻塞

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;
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。