ConcurrentHashMap

本文详细探讨了ConcurrentHashMap的实现原理,包括1.7版本的分段锁机制和1.8版本中结合CAS、volatile及synchronized的优化。在初始化阶段,通过循环CAS设置标记位确保线程安全。在put操作中,首次put会触发初始化,并使用CopyOnWrite策略避免并发问题。冲突处理采用了锁分离技术,提高并发性能。扩容过程中,多线程协作进行,利用hash值进行节点分类迁移,确保数据一致性。在扩容期间,get操作能从volatile变量中获取最新数据,若发现扩容进行中,则在新表中查找。
摘要由CSDN通过智能技术生成

1.7 分段锁

1.8 CAS + volatile + synchronized

初始化

private final Node<K,V>[] initTable() {
        Node<K,V>[] tab; int sc;
        while ((tab = table) == null || tab.length == 0) {
            //sizeCtl为-1时临时充当标记位,表明有线程在执行初始化了
            if ((sc = sizeCtl) < 0)
                Thread.yield(); // lost initialization race; just spin
            //long offset, int expected, int x
                // 设置sizeCtl,SIZECTL是sizeCtl在对象内存中的偏移量
            else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
                try {
                    if ((tab = table) == null || tab.length == 0) {
                        int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                        @SuppressWarnings("unchecked")
                        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                        table = tab = nt;
                        sc = n - (n >>> 2);
                    }
                } finally {
                    sizeCtl = sc;
                }
                break;
            }
        }
        return tab;
    }

 总的流程是,循环CAS设定标记位,只有设定成功的线程才能进行初始化,其他线程自旋等待

put

  • 第一次put时先进行初始化过程
  • 不允许key, value为null,抛异常
  • CopyOnWrite:每次重新取表的引用,表是volatile
  • 计算hashcode, 插入位置,判定冲突
    • 未冲突:循环CAS设定值直至成功,返回
    • 冲突:锁分离,锁住链表头对象再插入,提高并发程度
    • 扩容:协作扩容,扩容完毕再put

扩容

多线程并发扩容:

  • 当表长达到容量,再put时进行扩容
  • rehash时可以依据hash值在表的长度那一位的值是0还是1将节点分为两类
  • 比如说表长为8,一个节点的hash值为1,1111,1111,另一个为0,0110,1111,第二个会被放到新表中同一个索引位上,而第一个则会放到原始索引位+原始表长的位置上去
  • 锁住头节点,然后分类批量进行迁移

协作扩容:

  • 如果put时发现头节点hash值位负数,表示正进行扩容,这时put的线程就参与进行一起扩容,完成后再进行Put

扩容时get:

  • volatile包装拿到最新的节点数据,如果get时发现已迁移,则在新表中get

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值