ConcurrentHashMap的get方法需要加锁吗

不需要加锁。get方法是读操作,只需要保证在并发环境下的可见性即可。在ConcurrentHashMap(CHM)的代码实现中,是通过以下三点来保证get方法的可见性。

变量的可见性:如下代码所示,在CHM中有两个关键地方被volatile修饰:CHM中的数组table被volatile修饰;Node节点中的val和next被volatile修饰。数组table被volatile修饰,可以保证在哈希表发生扩容后,get方法可以获取到最新的table引用;Node节点的next指针和val变量也都被volatile修饰,可以保证链表的结构发生变动或者Node节点中的值发生变动后,get方法可以获取到最新的Node节点或Node节点中的值。

// table相关代码
class ConcurrentHashMap {
    transient volatile Node<K,V>[] table;
}
// Node相关代码
static class Node<K, V> implements Map.Entry<K,V> {
    final int hash;
    final K, key;
    volatile V val; // 被volatile修饰
    volatile Node<K,V> next; // 被volatile修饰
}

数组中元素的可见性:虽然成员变量tab被volatile修饰,但它只能保证数组引用tab的可见性,数组内部的元素是不具备可见性的。因此,在获取某个哈希桶中的头节点时,不能直接根据下标获取数据。get方法调用了tabAt()方法,该方法在底层调用了Unsafe.getObjectVolatile方法,通过插入内存屏障的方式,保证了拿到的头节点是最新的节点。

扩容期间的重定向:如果调用get方法时,哈希表正在扩容,且目标节点已被迁移到新的哈希表中,那么get方法会拿到一个ForwardingNode节点(该节点的hash值为-1),get方法会调用该节点的find()方法,到新的哈希表中查找对应的节点。

#HashMap##Java#
HashMap专栏 文章被收录于专栏

记录一些HashMap相关的面试题

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务