繁体   English   中英

ConcurrentHashMap.get() 如何防止脏读?

[英]How does ConcurrentHashMap.get() prevent dirty read?

我正在查看ConcurrentHashMap的源代码,想知道get()方法如何在没有任何监视器的情况下工作,代码如下:

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))) // mark here for possible dirty read
                    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)))) // mark here for possible dirty read
                    return e.val;
            }
        }
        return null;
    }

这两条线标志着我都在做同样的事情:检查是否key当前的Node<K, V>等于的key需要。 如果为true ,将返回其对应的值。 但是如果另一个线程在returnremove()之前从数据结构中切入这个节点呢? 由于局部变量e仍然持有被移除节点的引用,GC 会保留它,而get()方法仍然会返回被移除的值,从而导致脏读。

我错过了什么?

它没有

检索操作(包括get )通常不会阻塞,因此可能与更新操作(包括putremove )重叠。 检索反映了最近完成的更新操作的结果。 (更正式地,给定键的更新操作与报告更新值的该键的任何(非空)检索具有先发生关系。)

这通常不是问题,因为如果get方法获取了锁, get永远不会返回不可能发生的结果,从而阻塞其他线程中的更新操作。 您只会得到结果,就好像get调用发生在更新操作开始之前一样。

所以,如果你不介意get发生在更新之前还是之后,你也不应该介意它发生更新期间,因为duringbefore之间没有明显的区别。 如果您确实希望get在更新出现,那么您需要从更新线程发出更新完成的信号; 等待获取锁无论如何都不会实现,因为您可能会在更新发生之前获得锁(在这种情况下,您将获得与未获取锁相同的结果)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM