Java并发编程 concurrentHashmap和hashMap

今天来谈谈对concurrentHashmap的理解

concurrentHashmap其实是在hashMap的基础上进行的优化。
可以理解为是一个线程安全的hashMap, 在jdk1.7中,concurrentHashmap通过将16个初始位置分成16个segment来实现线程安全,每一个segment都有自己的reentrant lock来实现线程安全

jdk1.8改为通过16个node来实现线程安全,通过cas和synchronized来实现。

cas: compareAndSet(i,j,k)

下面贴源码:

    public V put(K var1, V var2) {
        return this.putVal(var1, var2, false);
    }
 
    final V putVal(K var1, V var2, boolean var3) {
        if (var1 != null && var2 != null) {
            int var4 = spread(var1.hashCode());
            int var5 = 0;
            ConcurrentHashMap.Node[] var6 = this.table;
 
            while(true) {
                int var8;
                while(var6 == null || (var8 = var6.length) == 0) {
                    var6 = this.initTable();
                }
 
                ConcurrentHashMap.Node var7;
                int var9;
                if ((var7 = tabAt(var6, var9 = var8 - 1 & var4)) == null) {
                    if (casTabAt(var6, var9, (ConcurrentHashMap.Node)null, new ConcurrentHashMap.Node(var4, var1, var2, (ConcurrentHashMap.Node)null))) {
                        break;
                    }
                } else {
                    int var10 = var7.hash;
                    if (var7.hash == -1) {
                        var6 = this.helpTransfer(var6, var7);
                    } else {
                        Object var11 = null;
                        synchronized(var7) {
                            if (tabAt(var6, var9) == var7) {
                                if (var10 < 0) {
                                    if (var7 instanceof ConcurrentHashMap.TreeBin) {
                                        var5 = 2;
                                        ConcurrentHashMap.TreeNode var18;
                                        if ((var18 = ((ConcurrentHashMap.TreeBin)var7).putTreeVal(var4, var1, var2)) != null) {
                                            var11 = var18.val;
                                            if (!var3) {
                                                var18.val = var2;
                                            }
                                        }
                                    }
                                } else {
                                    var5 = 1;
                                    ConcurrentHashMap.Node var13 = var7;
 
                                    while(true) {
                                        if (var13.hash == var4) {
                                            Object var14 = var13.key;
                                            if (var13.key == var1 || var14 != null && var1.equals(var14)) {
                                                var11 = var13.val;
                                                if (!var3) {
                                                    var13.val = var2;
                                                }
                                                break;
                                            }
                                        }
 
                                        ConcurrentHashMap.Node var15 = var13;
                                        if ((var13 = var13.next) == null) {
                                            var15.next = new ConcurrentHashMap.Node(var4, var1, var2, (ConcurrentHashMap.Node)null);
                                            break;
                                        }
 
                                        ++var5;
                                    }
                                }
                            }
                        }
 
                        if (var5 != 0) {
                            if (var5 >= 8) {
                                this.treeifyBin(var6, var9);
                            }
 
                            if (var11 != null) {
                                return var11;
                            }
                            break;
                        }
                    }
                }
            }
 
            this.addCount(1L, var5);
            return null;
        } else {
            throw new NullPointerException();
        }
    }

put方法中两个判断:
第一次如果链表的位置中没有元素,则用cas方法放入
如果有元素,用synchronized确保替换
最后根据链表的长度判定是否转化红黑树,放入链表的最后。

最后1.7和1.8中concurrenthashmap的区别

  1. 1.7使用segment(reentrant)来进行并发,1.8中通过cas+synchronized
  2. 1.7使用segment,为16个并发。1.8中使用node,每一个都相互独立提高效率
  3. 1.7没有使用红黑树

链表长度为什么超过8要转为红黑树?
默认的是链表结构,并不是一开始就是红黑树结构,因为链表比红黑数占用的空间较少;
hash冲突导致链表长度真正达到8的概率极小,约为一千万分之一,同时也考虑到红黑树查询比链表快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值