JDK 1.8

整体架构

由Node数组、单向链表、红黑树组成的,当我们初始化一个ConcurrentHashMap实例的时候,默认会初始化一个长度为16的数组,由于ConcurrentHashMap它的核心仍然是 哈希表,所以必然会存在哈希冲突的情况,所以,ConcurrentHashMap采用拉链法来解决哈希冲突,当哈希冲突较多的时候,会造成链表长度较长的问题,会造成ConcurrentHashMap中一个数组元素的查询效率降低,因此为了解决这个问题,当数组长度>64,链表长度>8的时候,单向链表就会转化成红黑树;另外,一旦红黑树的元素个数小于等于6时,红黑树就会转化为单向链表

注意:使用treefyBin()方法将链表转化成红黑树

concurrenthashmap多线程 java java concurrenthashmap原理_链表

基本功能

ConcurrentHashMap本质上是一个HashMap,但是ConcurrentHashMap在HashMap的基础上,提供了并发安全的一个实现
如何保证并发安全?主要是通过对Node节点加锁,来保证数据更新安全的安全性

性能方面的优化

如何在数据安全和并发性能之间做好平衡,在很多地方都有类似的设计,例如:CPU的三级缓存、mysql的buffer_pool、synchronized的锁升级等等
ConcurrentHashMap也做了一个类似的优化
1、JDK 1.8中锁的粒度是数组中某一个节点,与JDK 1.7锁住一个Segment相比,锁的范围更小,性能更优
2、在对ConcurrentHashMap执行插入操作时,如果该数组中的某一节点为空,则进行一个CAS操作完成插入,如果数组中的某一节点不为空,再对该节点上锁;在对ConcurrentHashMap执行读取操作时,由于Node节点的value值和next指针都是用volatile修饰的,保证了可见性,所以读取数据是不需要上锁的,每次获取的都是最新值
3、引入红黑树,降低数据查询的复杂度,红黑树的查询时间复杂度是O(logN)
4、ConcurrentHashMap引入了多线程并发扩容的一个实现,多个线程对原始数组进行分片,分片之后,每个线程去进行一个分片的数据迁移,从而提升了扩容过程中数据迁移的效率