ConcurrentHashMap原理分析

本文主要分析了ConcurrentHashMap的初始化过程和put操作。在 JDK 1.5 后,ConcurrentHashMap 通过分段锁技术提升并发性能,而 JDK 8 则采用 CAS + synchronized 的组合。在初始化时,它会根据指定容量计算sizeCtl值,并在扩容时调整。在put过程中,当链表长度达到8时,ConcurrentHashMap可能选择扩容而非转换为红黑树。
摘要由CSDN通过智能技术生成

写在前边的一些话:在jdk1.5之前,HashTable为了保证线程安全,在每个方法上都加上了synchronized关键字,在并发场景下效率是特别低的。在1.5之后使用ConcurrentHashMap对它进行了替代,使用分段锁的技术,在使用时只需要将元素所在的段锁住,因此段与段之间是可以高并发的。在jdk8之后使用CAS+synchronized的组合方式来实现并发场景下的线程安全。

1、初始化

public ConcurrentHashMap(int initialCapacity) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException();
        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
        this.sizeCtl = cap;
    }

在ConcurrentHashMap中提供了一个空的构造函数用来创建一个新的并且默认大小是16的空Map。当指定初始化容量时,计算了sizeCtl=(1.5*initialCapacity +1),然后向上取最近的2的n次方。

sizeCtl为负值表示的table正在被初始化(-1)或者扩容(-(1+当前正在扩容线程的数量)),table为null时,该值默认为0。通常在扩容之后,将sizeCtl设置为下次需要扩容的阈值(0.75*n)。

2、put过程分析

  1. 这里我们应该注意到的是:与HashMap不同的是,在链表的长度达到8时有可能不会进行红黑树转换而仅仅做的是数组的扩容
final V putVal(K key, V value, boolean onlyIfAbsent) {
        //这里判断key和value都不能为空,如果为空就抛出异常
        if (key == null ||
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值