• Java:ConcurrentHashMap支持完全并发的读


    ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。(事实上,ConcurrentHashMap支持完全并发的读以及一定程度并发的写。)如果使用传统的技术,如HashMap中的实现,如果允许可以在hash链的中间添加或删除元素,读操作不加锁将得到不一致的数据。但是ConcurrentHashMap实现技术是保证HashEntry几乎是不可变的。HashEntry代表每个hash链中的一个节点,其结构如下所示: 

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. static final class HashEntry<K,V> {  
    2.         final K key;  
    3.         final int hash;  
    4.         volatile V value;  
    5.         final HashEntry<K,V> next;  
    6.   
    7.         HashEntry(K key, int hash, HashEntry<K,V> next, V value) {  
    8.             this.key = key;  
    9.             this.hash = hash;  
    10.             this.next = next;  
    11.             this.value = value;  
    12.         }  
    13.   
    14.     @SuppressWarnings("unchecked")  
    15.     static final <K,V> HashEntry<K,V>[] newArray(int i) {  
    16.         return new HashEntry[i];  
    17.     }  
    18.     }  


    可以看到除了value不是final的,其它值都是final的,这意味着不能从hash链的中间或尾部添加或删除节点,因为这需要修改next引用值,所有的节点的修改只能从头部开始。对于put操作,可以一律添加到Hash链的头部。但是对于remove操作,可能需要从中间删除一个节点,这就需要将要删除节点的前面所有节点整个复制一遍,最后一个节点指向要删除结点的下一个结点。为了确保读操作能够看到最新的值,将value设置成volatile,这避免了加锁。 remove操作要注意一个问题:如果某个读操作在删除时已经定位到了旧的链表上,那么此操作仍然将能读到数据,只不过读取到的是旧数据而已,这在多线程里面是没有问题的。
    HashEntry 类的 value 域被声明为 Volatile 型,Java 的内存模型可以保证:某个写线程对 value 域的写入马上可以被后续的某个读线程“看”到。在 ConcurrentHashMap 中,不允许用 null作为键和值,当读线程读到某个 HashEntry 的 value 域的值为 null 时,便知道产生了冲突——发生了重排序现象,需要加锁后重新读入这个 value 值。这些特性互相配合,使得读线程即使在不加锁状态下,也能正确访问 ConcurrentHashMap。 

    在看源码实现时,对HashEntry 的 value 域的值可能为 null有些疑惑,网上都是说发生了重排序现象,后来仔细想想不完全正确,重排序发生在删除操作时,这只是其中的一个原因,尽管ConcurrentHashMap不允许将value为null的值加入,但现在仍然能够读到一个为空的value就意味着此值对当前线程还不可见,主要因为HashEntry还没有完全构造完成导致的,所以对添加和删除(对链表的结构性修改都可能会导致value为null)。

    转自:http://blog.csdn.net/enjoyinwind/article/details/41148895

  • 相关阅读:
    Hibernate 中 get()和load()的区别
    Socket网络编程
    经典
    jsp的九大内置对象及EL表达式的隐含对象
    TreeSet
    centos7.4安装npm
    centos7.4中安装docker
    centos7安装nginx
    centos中安装基础环境
    在docker中安装mysql
  • 原文地址:https://www.cnblogs.com/slwenyi/p/6393829.html
Copyright © 2020-2023  润新知