美文网首页前端程序员干货程序员计算机微刊
七.线程同步容器-ConcurrentHashMap

七.线程同步容器-ConcurrentHashMap

作者: 蜗牛1991 | 来源:发表于2017-09-19 23:37 被阅读14次

一.层次图

image.png

二.结构

  • 参数
 static final int DEFAULT_INITIAL_CAPACITY = 16;//容量
 static final float DEFAULT_LOAD_FACTOR = 0.75f;//扩容因子
  static final int DEFAULT_CONCURRENCY_LEVEL = 16;//并发度,程序运行时能够同时更新且不产生锁竞争的最大线程数

 private transient final int hashSeed = randomHashSeed(this)//0;
  • 结构
    //hash表分段集合
    final Segment<K,V>[] segments; 
    //Segment(桶)
    static final class Segment<K,V> extends ReentrantLock implements Serializable {
        transient volatile HashEntry<K,V>[] table;
        transient int count;
        transient int modCount;
        transient int threshold(capacity *loadFactor);
        final float loadFactor;
    }
  //HashEntry(节点)(数组加链表)
  static final class HashEntry<K,V> {
        final int hash;
        final K key;
        volatile V value;
        volatile HashEntry<K,V> next;
}
  • 初始化
    ConcurrentHashMap初始化时,计算出Segment数组的大小ssize和每个Segment中HashEntry数组的大小cap,并初始化Segment数组的第一个元素;其中ssize大小为2的幂次方,默认为16,cap大小也是2的幂次方,最小值为2,计算过程如下:
 public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {  
        int ssize = 1;
        while (ssize < concurrencyLevel) {
            ++sshift;
            ssize <<= 1;
        }
        ......
        int c = initialCapacity / ssize;
        if (c * ssize < initialCapacity)
            ++c;
        int cap = MIN_SEGMENT_TABLE_CAPACITY;//2
        while (cap < c)
            cap <<= 1;//<<1相当于*2
        Segment<K,V> s0 = new Segment<K,V>(loadFactor, (int)(cap * loadFactor),(HashEntry<K,V>[])new HashEntry[cap]);
        Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
        this.segments = ss;
    }
image.png

三.加锁机制

  • 它与HashTable 使用synchronized对整个容器加锁不同,ConcurrentHashMap可以做到进行读操作时不用加锁,进行写操作的时候只需要锁住对应分段的哈希桶即可,而不用对整个容器加锁。
  • put加锁
//根据key的hash找到对应的Segment执行put方法
public V put(K key, V value) {
        Segment<K,V> s;
          ...
        return s.put(key, hash, value, false);
    }
  final V put(K key, int hash, V value, boolean onlyIfAbsent) {
            HashEntry<K,V> node = tryLock() ? null :
                scanAndLockForPut(key, hash, value);
            V oldValue;
            .....
            } finally {
                unlock();
            }
            return oldValue;
        }

推荐阅读:深入分析ConcurrentHashMap

相关文章

网友评论

    本文标题:七.线程同步容器-ConcurrentHashMap

    本文链接:https://www.haomeiwen.com/subject/srgbsxtx.html