• ConcurrentHashMap之实现细节2


    数据结构

    关于Hash表的基础数据结构,这里不想做过多的探讨。Hash表的一个很重要方面就是如何解决hash冲突,ConcurrentHashMap 和HashMap使用相同的方式,都是将hash值相同的节点放在一个hash链中。与HashMap不同的是,ConcurrentHashMap使用 多个子Hash表,也就是段(Segment)。下面是ConcurrentHashMap的数据成员:

    Java代码 <embed height="15" width="14" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="always" quality="high" flashvars="clipboard=public%20class%20ConcurrentHashMap%3CK%2C%20V%3E%20extends%20AbstractMap%3CK%2C%20V%3E%0A%20%20%20%20%20%20%20%20implements%20ConcurrentMap%3CK%2C%20V%3E%2C%20Serializable%20%7B%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20Mask%20value%20for%20indexing%20into%20segments.%20The%20upper%20bits%20of%20a%0A%20%20%20%20%20*%20key's%20hash%20code%20are%20used%20to%20choose%20the%20segment.%0A%20%20%20%20%20*%2F%0A%20%20%20%20final%20int%20segmentMask%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20Shift%20value%20for%20indexing%20within%20segments.%0A%20%20%20%20%20*%2F%0A%20%20%20%20final%20int%20segmentShift%3B%0A%0A%20%20%20%20%2F**%0A%20%20%20%20%20*%20The%20segments%2C%20each%20of%20which%20is%20a%20specialized%20hash%20table%0A%20%20%20%20%20*%2F%0A%20%20%20%20final%20Segment%3CK%2CV%3E%5B%5D%20segments%3B%0A%7D" src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" lk_mediaid="lk_juiceapp_mediaPopup_1236652704279" lk_media="yes">
    1. public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>  
    2.         implements ConcurrentMap<K, V>, Serializable {  
    3.     /**
    4.       * Mask value for indexing into segments. The upper bits of a
    5.       * key's hash code are used to choose the segment.
    6.       */  
    7.     final int segmentMask;  
    8.   
    9.     /**
    10.       * Shift value for indexing within segments.
    11.       */  
    12.     final int segmentShift;  
    13.   
    14.     /**
    15.       * The segments, each of which is a specialized hash table
    16.       */  
    17.     final Segment<K,V>[] segments;  
    18. }  
    public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable { /** * Mask value for indexing into segments. The upper bits of a * key's hash code are used to choose the segment. */ final int segmentMask; /** * Shift value for indexing within segments. */ final int segmentShift; /** * The segments, each of which is a specialized hash table */ final Segment<K,V>[] segments; }

    所有的成员都是final的,其中segmentMask和segmentShift主要是为了定位段,参见上面的segmentFor方法。

    每个Segment相当于一个子Hash表,它的数据成员如下:

    Java代码 <embed height="15" width="14" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="always" quality="high" flashvars="clipboard=%20%20%20%20static%20final%20class%20Segment%3CK%2CV%3E%20extends%20ReentrantLock%20implements%20Serializable%20%7B%0Aprivate%20static%20final%20long%20serialVersionUID%20%3D%202249069246763182397L%3B%0A%20%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20%20*%20The%20number%20of%20elements%20in%20this%20segment's%20region.%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20transient%20volatile%20int%20count%3B%0A%0A%20%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20%20*%20Number%20of%20updates%20that%20alter%20the%20size%20of%20the%20table.%20This%20is%0A%20%20%20%20%20%20%20%20%20*%20used%20during%20bulk-read%20methods%20to%20make%20sure%20they%20see%20a%0A%20%20%20%20%20%20%20%20%20*%20consistent%20snapshot%3A%20If%20modCounts%20change%20during%20a%20traversal%0A%20%20%20%20%20%20%20%20%20*%20of%20segments%20computing%20size%20or%20checking%20containsValue%2C%20then%0A%20%20%20%20%20%20%20%20%20*%20we%20might%20have%20an%20inconsistent%20view%20of%20state%20so%20(usually)%0A%20%20%20%20%20%20%20%20%20*%20must%20retry.%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20transient%20int%20modCount%3B%0A%0A%20%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20%20*%20The%20table%20is%20rehashed%20when%20its%20size%20exceeds%20this%20threshold.%0A%20%20%20%20%20%20%20%20%20*%20(The%20value%20of%20this%20field%20is%20always%20%3Ctt%3E(int)(capacity%20*%0A%20%20%20%20%20%20%20%20%20*%20loadFactor)%3C%2Ftt%3E.)%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20transient%20int%20threshold%3B%0A%0A%20%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20%20*%20The%20per-segment%20table.%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20transient%20volatile%20HashEntry%3CK%2CV%3E%5B%5D%20table%3B%0A%0A%20%20%20%20%20%20%20%20%2F**%0A%20%20%20%20%20%20%20%20%20*%20The%20load%20factor%20for%20the%20hash%20table.%20%20Even%20though%20this%20value%0A%20%20%20%20%20%20%20%20%20*%20is%20same%20for%20all%20segments%2C%20it%20is%20replicated%20to%20avoid%20needing%0A%20%20%20%20%20%20%20%20%20*%20links%20to%20outer%20object.%0A%20%20%20%20%20%20%20%20%20*%20%40serial%0A%20%20%20%20%20%20%20%20%20*%2F%0A%20%20%20%20%20%20%20%20final%20float%20loadFactor%3B%0A%7D" src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" lk_mediaid="lk_juiceapp_mediaPopup_1236652704286" lk_media="yes">
    1.     static final class Segment<K,V> extends ReentrantLock implements Serializable {  
    2. private static final long serialVersionUID = 2249069246763182397L;  
    3.         /**
    4.           * The number of elements in this segment's region.
    5.           */  
    6.         transient volatile int count;  
    7.   
    8.         /**
    9.           * Number of updates that alter the size of the table. This is
    10.           * used during bulk-read methods to make sure they see a
    11.           * consistent snapshot: If modCounts change during a traversal
    12.           * of segments computing size or checking containsValue, then
    13.           * we might have an inconsistent view of state so (usually)
    14.           * must retry.
    15.           */  
    16.         transient int modCount;  
    17.   
    18.         /**
    19.           * The table is rehashed when its size exceeds this threshold.
    20.           * (The value of this field is always <tt>(int)(capacity *
    21.           * loadFactor)</tt>.)
    22.           */  
    23.         transient int threshold;  
    24.   
    25.         /**
    26.           * The per-segment table.
    27.           */  
    28.         transient volatile HashEntry<K,V>[] table;  
    29.   
    30.         /**
    31.           * The load factor for the hash table.   Even though this value
    32.           * is same for all segments, it is replicated to avoid needing
    33.           * links to outer object.
    34.           * @serial
    35.           */  
    36.         final float loadFactor;  
    37. }  
    static final class Segment<K,V> extends ReentrantLock implements Serializable { private static final long serialVersionUID = 2249069246763182397L; /** * The number of elements in this segment's region. */ transient volatile int count; /** * Number of updates that alter the size of the table. This is * used during bulk-read methods to make sure they see a * consistent snapshot: If modCounts change during a traversal * of segments computing size or checking containsValue, then * we might have an inconsistent view of state so (usually) * must retry. */ transient int modCount; /** * The table is rehashed when its size exceeds this threshold. * (The value of this field is always <tt>(int)(capacity * * loadFactor)</tt>.) */ transient int threshold; /** * The per-segment table. */ transient volatile HashEntry<K,V>[] table; /** * The load factor for the hash table. Even though this value * is same for all segments, it is replicated to avoid needing * links to outer object. * @serial */ final float loadFactor; }

    count用来统计该段数据的个数,它是volatile,它用来协调修改和读取操作,以保证读取操作能够读取到几乎最新的修改。协调方式是这样的,每次 修改操作做了结构上的改变,如增加/删除节点(修改节点的值不算结构上的改变),都要写count值,每次读取操作开始都要读取count的值。这利用了 Java 5中对volatile语义的增强,对同一个volatile变量的写和读存在happens-before关系。modCount统计段结构改变的次 数,主要是为了检测对多个段进行遍历过程中某个段是否发生改变,在讲述跨段操作时会还会详述。threashold用来表示需要进行rehash的界限 值。table数组存储段中节点,每个数组元素是个hash链,用HashEntry表示。table也是volatile,这使得能够读取到最新的 table值而不需要同步。loadFactor表示负载因子。

  • 相关阅读:
    删除变长列字段后使用DBCC CLEANTABLE回收空间
    python笔记25-mock-server之moco
    python笔记24-unittest单元测试之mock.patch
    python笔记23-unittest单元测试之mock
    python接口自动化16-multipart/form-data上传图片
    python笔记22-literal_eval函数处理返回json中的单双引号
    初识PCA数据降维
    Android工具包
    Matlab中unifrnd函数使用解析
    Matlab中min/max函数的误解
  • 原文地址:https://www.cnblogs.com/danghuijian/p/4400694.html
Copyright © 2020-2023  润新知