ConcurrentHashMap源码之put和get方法

以下ConcurrentHashMap类是基于jdk1.7来分析。

JDK1.7中ConcurrentHashMap是通过segments数组和HashEntry数组+链表来进行实现的。利用锁分段技术,支持任务数量线程的读和一定数量线程的写。

我们看下ConcurrentHashMap是怎么进行put和get操作的。

1、ConcurrentHashMap的put方法不能插入null值(为什么?自行百度),在put kv值时,首先取key的hash值,通过hash值判断key所在的segment,然后使用unsafe类的本地方法获取此segments数组中hash值对应的segment是否为null(为什么用unsafe类呢?因为需要获取内存中最新的存储值,关于unsafe类直接操作内存,参考这里。),如果为null,则初始化segment元素,然后调用segment的put方法。ConcurrentHashMap类的put方法源码如下

//ConcurrentHashMap的put方法
public V put(K key, V value) {
        Segment<K,V> s;
//value值为null,直接报异常
        if (value == null)
            throw new NullPointerException();
//两次hash,获得key的哈希值
        int hash = hash(key);
//对hash值的高位和segmentMask掩码做按位与,确定key所在的segment(segmentMask=segment的长度-1)
        int j = (hash >>> segmentShift) & segmentMask;
//通过Unsafe类获取segments数组中下标为j的元素,如果不存在就初始化segment。(SSHIFT和SBASE均为确定数组元素的内存位置,见以下变量声明和static块初始化)
        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
             (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
            s = ensureSegment(j);
        return s.put(key, hash, value, false);
    }

// Unsafe mechanics
    private static final sun.misc.Unsafe UNSAFE;
    private static final long SBASE;
    private static final int SSHIFT;
    private static final long TBASE;
    private static final int TSHIFT;
    private static final long HASHSEED_OFFSET;
    private static final long SEGSHIFT_OFFSET;
    private static final long SEGMASK_OFFSET;
    private static final long SEGMENTS_OFFSET;
    static {
        int ss, ts;
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class tc = HashEntry[].class;
            Class sc = Segment[].class;
            TBASE = UNSAFE.arrayBaseOffset(tc);
            SBASE = UNSAFE.arrayBaseOffset(sc);
            ts = UNSAFE.arrayIndexScale(tc);
            ss = UNSAFE.arrayIndexScale(sc);
            HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
                ConcurrentHashMap.class.getDeclaredField("hashSeed"));
            SEGSHIFT_OFFSET
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值