ConcurrentHashMap--原理

IT利刃出鞘 2021-09-15 09:17:41
java


原文网址:ConcurrentHashMap--原理\_IT利刃出鞘的博客-CSDN博客

其他网址

ConcurrentHashMap源码解析 JDK8\_沈世钧的博客-CSDN博客
详解ConcurrentHashMap及JDK8的优化\_全菜工程师小辉的博客-CSDN博客
ConcurrentHashMap源码分析(JDK8版本)\_惟愿无事-CSDN博客

Hashmap1.7和1.8区别+ConcurrentHashmap1.7和1.8区别\_hellodake的博客-CSDN博客

简介

JDK7与JDK8区别

> <table align="center"><tbody><tr><td><p></p></td><td><p>JDK1.7</p></td><td><p>JDK1.8</p></td></tr><tr><td><p>机制</p></td><td><p>ReentrantLock+Segment+HashEntry(数组加链表)</p></td><td><p>synchronized+CAS+HashEntry(数组加链表)+红黑树</p><p>读操作:volatile;写操作:synchronized+CAS</p></td></tr><tr><td><p>粒度</p></td><td><p>对需要进行数据操作的Segment加锁</p></td><td><p>对每个桶(数组项)加锁</p></td></tr></tbody></table>

JDK7

        在JDK1.7中ConcurrentHashMap采用了ReentrantLock+Segment+HashEntry(数组加链表)的方式实现。

        ConcurrentHashMap中的分段锁称为Segment,它类似于HashMap的结构,即:内部拥有一个Entry数组,数组中的每个元素又是一个链表,同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

        ConcurrentHashMap使用分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。 

ConcurrentHashMap的内部结构图

ConcurrentHashMap的内部结构图

put过程

  1. 对key进行第1次hash,通过hash值确定Segment的位置
  2. 在Segment内进行操作,获取锁
  3. 获取当前Segment的HashEntry数组后对key进行第2次hash,通过hash值确定在HashEntry数组的索引位置(头部)
  4. 通过继承ReentrantLock的tryLock方法尝试去获取锁,如果获取成功就直接插入相应的位置,如果已经有线程获取该Segment的锁,那当前线程会以自旋的方式去继续的调用tryLock方法去获取锁,超过指定次数就挂起,等待唤醒
  5. 然后对当前索引的HashEntry链进行遍历,如果有重复的key,则替换;如果没有重复的,则插入到链头
  6. 释放锁 

get操作

和put操作类似,也是要两次hash。但是get操作的Concurrenthashmap不需要加锁,原因是存储元素都标记了volatile。 

size操作

        size操作就是遍历两次所有的Segments,每次记录Segment的modCount值,然后将两次的modCount进行比较

  • 如果相同,则表示期间没有发生过写入操作,就将原先遍历的结果返回。
  • 如果经判断发现两次统计出的modCount并不一致,要全部Segment加锁来进行count的获取和统计。在此期间每个Segement都被锁住,无法进行其他操作,统计出的count自然很准确。

此结构优缺点

优点

  1. 写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment。

缺点

  1. Hash的过程要比普通的HashMap要长

JDK8

概述

        JDK8中ConcurrentHashMap结构基本上和HashMap一样,采用了(synchronized+CAS+HashEntry(数组加链表)+红黑树)的实现方式来设计。读操作使用CAS,写操作使用synchronized。

        JDK8中彻底放弃了Segment转而采用的是Node,其设计思想也不再是JDK1.7中的分段锁思想。

        Node:保存key,value及key的hash值的数据结构。其中value和next都用volatile修饰,保证并发的可见性。

class Node<K,V>implements Map.Entry<K,V>
{final int hash;final K key;volatile V val;volatile Node<K,V> next;//... 省略部分代码}

        在JDK8中ConcurrentHashMap的结构,由于引入了红黑树,使得ConcurrentHashMap的实现非常复杂,我们都知道,红黑树是一种性能非常好的二叉查找树,其查找性能为O(logN),但是其实现过程也非常复杂,而且可读性也非常差,DougLea的思维能力确实不是一般人能比的,早期完全采用链表结构时Map的查找时间复杂度为O(N),JDK8中ConcurrentHashMap在链表的长度大于某个阈值(8)的时候会将链表转换成红黑树进一步提高其查找性能。

size方法

ConcurrentHashMap怎么确定数组的大小?

JDK8

初始化

put

        使用CAS操作,.......。

        线程访问哈希表的bucket时,使用 sychronizeded关键字,防止多个线程同时操作同一个 bucket(即锁住bucket)。如果该结点的 hash值不少于0,则遍历链表更新节点或插入新节点;如果该节点是TreeBin类型的节点,说明是红黑树结构,则通过putTreeVal方法往红黑树中插入节点;更新了节点数量,还要考虑扩容和链表转红黑树。

final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
if (binCount >= TREEIFY_THRESHOLD)

get

get操作可以无锁(不加锁)是由于 Node 元素 的val 指针 和 next指针 用volatile修饰的,在多线程环境下,线程A修改结点的 val 或者新增结点的时候,对线程B都是可见的。

size

版权声明
本文为[IT利刃出鞘]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000040685449

  1. 快速从 Windows 切换到 Linux 环境
  2. 五分钟向MySql数据库插入一千万条数据
  3. Java日期时间API系列42-----一种高效的中文日期格式化和解析方法
  4. 用Java实现红黑树
  5. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现
  6. 海量列式非关系数据库HBase 架构,shell与API
  7. Architecture, Shell et API de base de données non relationnelle à grande échelle
  8. Mise en œuvre de l'arbre Rouge et noir en Java
  9. Java Date Time API Series 42 - - a efficient Chinese Date Format and Analysis Method
  10. 5 minutes pour insérer 10 millions de données dans la base de données MySQL
  11. Passage rapide de Windows à l'environnement Linux
  12. Notes on Java backend development of PostgreSQL (I)
  13. 海量列式非關系數據庫HBase 架構,shell與API
  14. Byte Jump the latest open source, the most Classic hashtap Graph details,
  15. L'interview Java de Byte Hopping Society, l'analyse super populaire de l'utilisation et du code source de countdownlatch,
  16. "Anti Mafia storm" Wang Zhifei's love history is really wonderful: he divorced Zhang Xinyi and married a 14-year-old wife
  17. In spring in the jade mansion, Jia Fengyuan was not moved by his brother's death. Why was su Yingxue changed? The reason is realistic
  18. Adam Oracle Oracle fully constructs Adam token incentive for ecological development
  19. 实战SpringCloud通用请求字段拦截处理,超过500人面试阿里,
  20. 宅家36天咸鱼翻身入职腾讯,Zookeeper一致性级别分析,
  21. The first starcoin & move hacksong source code analysis - P (a)
  22. Zhaijia 36 days Salt Fish turn into Tencent, Zookeeper Consistency level analysis,
  23. Traitement de l'interception des champs de demande communs de Spring Cloud, plus de 500 personnes interviewent Ali,
  24. About JavaScript modules
  25. Object oriented programming (2)
  26. Java日期时间API系列42-----一种高效的中文日期格式化和解析方法
  27. Java日期時間API系列42-----一種高效的中文日期格式化和解析方法
  28. 宅家36天鹹魚翻身入職騰訊,Zookeeper一致性級別分析,
  29. Java Date Time API Series 42 - - a efficient Chinese Date Format and Analysis Method
  30. 已成功拿下字节、腾讯、脉脉offer,7年老Java一次操蛋的面试经历,
  31. 小米Java社招面试,每次面试必问的二叉树的设计与编码,
  32. 小米Java校招面试,阿里、百度、美团、携程、蚂蚁面经分享,
  33. 小米Java校招面試,阿裏、百度、美團、攜程、螞蟻面經分享,
  34. Xiaomi Java School Recruitment interview, Ali, baidu, meituan, ctrip, ant Facebook Sharing,
  35. La conception et le codage de l'arbre binaire requis pour chaque entrevue d'embauche de la société Java millet;
  36. A remporté avec succès Byte, Tencent, Pulse offer, 7 ans Java une expérience d'entrevue de baise,
  37. 干货来袭,Java岗面试12家大厂成功跳槽,
  38. 常用Java框架面试题目,现在做Java开发有前途吗?
  39. 常用Java框架面試題目,現在做Java開發有前途嗎?
  40. Les questions d'entrevue couramment utilisées pour le cadre Java sont - elles prometteuses pour le développement Java?
  41. L'arrivée de marchandises sèches, l'entretien d'emploi Java 12 grandes usines ont réussi à changer d'emploi,
  42. Multiple postures for handling container time in k8s environment
  43. Echarts remove left Gap, Blank
  44. Hotspot Weekly | zoom $100 million, docker fees, $38 billion Data bricks
  45. JsonMappingException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory...
  46. Java. Security. Securerandom source code analysis Java. Security. EGD = file: / dev /. / urandom
  47. When using IntelliJ idea, jump directly and quickly from the mapper interface to mapper.xml
  48. When idea writes SQL in mybatis XML, the solution to the problems of table name, field and red reporting
  49. Spring cloud integrates Nacos
  50. 应届毕业生Java笔试题目,2021大厂Java社招最全面试题,
  51. Liver explosion! Take you to understand Hadoop serialization
  52. linux系列之:告诉他,他根本不懂kill
  53. java版gRPC实战之三:服务端流
  54. RabbitMQ核心知识总结!
  55. linux系列之:告诉他,他根本不懂kill
  56. java版gRPC实战之三:服务端流
  57. RabbitMQ核心知识总结!
  58. 10天拿到字节跳动Java岗位offer,学习Java开发的步骤
  59. 10天拿到字节跳动Java岗位offer,Java知识点思维导图
  60. Résumé des connaissances de base de rabbitmq!