ConcurrentHashMap 原理介绍

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

本文对JDK1.7与1.8中ConcurrentHashMap的并发设计做了精简的笼统的介绍,方便大家在学习,面试或者父子的时候进行参考。

1. Hashtable

Hashtable也是线程安全的Hash表,但是其底层的实现非常简单粗暴,就是直接对增删改操作的整张Hash表加锁,为了减小锁的粒度,取得更好的并发性能,JUC包提供了ConcurrentHashMap,在本文,我们介绍一下JDK 1.7以及JDK 1.8中ConcurrentHashMap的实现,供大家学习理解。

2. JDK 1.7

在JDK 1.7中,ConcurrentHashMap 采用的是分段锁的机制,以减小锁的粒度。

为了减小锁的粒度,JDK 1.7中的ConcurrentHashMap在Hashtable的基础上加了一层Hash分层,对应key值的kv对会hash到对应的HashTable上,当需要对某一小HashTable并发操作时,只需要锁住对应的小HashTable即可。

3. JDK 1.8

在JDK 1.8中,ConcurrentHashMap 锁的是对应的Hash分槽。

当某一个进行修改操作时,会锁住该hash槽对应的头节点,然而,这种操作会给hash扩容单来困扰,因此,DK 1.8的ConcurrentHashMap采用了COW的形式,当需要进行扩容时,会新建一个容量为现在两倍的ConcurrentHashMap,然后进行协同迁移操作,数据迁移完成后,将指针指向新的ConcurrentHashMap,完成扩容操作。

协同迁移的过程中,所有对ConcurrentHashMap进行操作的线程都会被拉入协同扩容的过程中,每个线程会分到一些哈希槽的迁移任务并且同一个槽的任务不会被多个线程分配到。

另外,JDK 1.8的ConcurrentHashMap在统计kv对的数量时,也做了优化,改为使用一个链表统计总数,当链表中的某一位有线程在修改时,当前线程会顺着链表找到下一位空闲的node节点做容量的更新,以提高并发性能。

猜你喜欢

转载自juejin.im/post/7126568318156308494
今日推荐