背景

上文JDK8中的HashMap源码写了HashMap,这次写ConcurrentHashMap

ConcurrentHashMap源码

  1. /**
  2. * Maps the specified key to the specified value in this table.
  3. * Neither the key nor the value can be null.
  4. *
  5. * <p>The value can be retrieved by calling the {@code get} method
  6. * with a key that is equal to the original key.
  7. *
  8. * @param key key with which the specified value is to be associated
  9. * @param value value to be associated with the specified key
  10. * @return the previous value associated with {@code key}, or
  11. * {@code null} if there was no mapping for {@code key}
  12. * @throws NullPointerException if the specified key or value is null
  13. */
  14. public V put(K key, V value) {
  15. return putVal(key, value, false);
  16. }
  17.  
  18. /** Implementation for put and putIfAbsent */
  19. final V putVal(K key, V value, boolean onlyIfAbsent) {
  20. if (key == null || value == null) throw new NullPointerException();
  21. int hash = spread(key.hashCode());
  22. int binCount = 0;
  23. for (Node<K,V>[] tab = table;;) {
  24. Node<K,V> f; int n, i, fh;
  25. //tab为空,则初始化
  26. if (tab == null || (n = tab.length) == 0)
  27. tab = initTable();
  28. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { //该槽为空,则尝试插入
  29. if (casTabAt(tab, i, null,
  30. new Node<K,V>(hash, key, value, null)))
  31. break; // no lock when adding to empty bin
  32. }
  33. else if ((fh = f.hash) == MOVED) //正在移动,
  34. tab = helpTransfer(tab, f);
  35. else {
  36. V oldVal = null;
  37. synchronized (f) { //对该槽进行加锁
  38. if (tabAt(tab, i) == f) {
  39. if (fh >= 0) {
  40. binCount = 1;
  41. for (Node<K,V> e = f;; ++binCount) {
  42. K ek;
  43. if (e.hash == hash &&
  44. ((ek = e.key) == key ||
  45. (ek != null && key.equals(ek)))) {
  46. oldVal = e.val;
  47. if (!onlyIfAbsent)
  48. e.val = value;
  49. break;
  50. }
  51. Node<K,V> pred = e;
  52. if ((e = e.next) == null) {
  53. pred.next = new Node<K,V>(hash, key,
  54. value, null);
  55. break;
  56. }
  57. }
  58. }
  59. else if (f instanceof TreeBin) {
  60. Node<K,V> p;
  61. binCount = 2;
  62. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
  63. value)) != null) {
  64. oldVal = p.val;
  65. if (!onlyIfAbsent)
  66. p.val = value;
  67. }
  68. }
  69. }
  70. }
  71. if (binCount != 0) {
  72. if (binCount >= TREEIFY_THRESHOLD)
  73. treeifyBin(tab, i);
  74. if (oldVal != null)
  75. return oldVal;
  76. break;
  77. }
  78. }
  79. }
  80. addCount(1L, binCount);
  81. return null;
  82. }
  83. /**
  84. * Returns the value to which the specified key is mapped,
  85. * or {@code null} if this map contains no mapping for the key.
  86. *
  87. * <p>More formally, if this map contains a mapping from a key
  88. * {@code k} to a value {@code v} such that {@code key.equals(k)},
  89. * then this method returns {@code v}; otherwise it returns
  90. * {@code null}. (There can be at most one such mapping.)
  91. *
  92. * @throws NullPointerException if the specified key is null
  93. */
  94. public V get(Object key) {
  95. Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
  96. //获得hash值
  97. int h = spread(key.hashCode());
  98. //表非空,且该处不为空
  99. if ((tab = table) != null && (n = tab.length) > 0 &&
  100. (e = tabAt(tab, (n - 1) & h)) != null) {
  101. if ((eh = e.hash) == h) { //判断第1个
  102. if ((ek = e.key) == key || (ek != null && key.equals(ek)))
  103. return e.val;
  104. }
  105. else if (eh < 0) //eh<0,找其他的
  106. return (p = e.find(h, key)) != null ? p.val : null;
  107. while ((e = e.next) != null) { //遍历
  108. if (e.hash == h &&
  109. ((ek = e.key) == key || (ek != null && key.equals(ek))))
  110. return e.val;
  111. }
  112. }
  113. return null;
  114. }

ConcurrentHashMap代码太多了,粘了好几次粘不上来。只粘几个方法吧。

阅后感

ConcurrentHashMap通过几个原子操作尽量减少加锁操作。

扩容部分没有看太明白,尤其时扩容时进行get操作。后续再继续学习。

JDK8中的ConcurrentHashMap源码的更多相关文章

  1. JDK8中的HashMap源码

    背景 很久以前看过源码,但是猛一看总感觉挺难的,很少看下去.当时总感觉是水平不到.工作中也遇到一些想看源码的地方,但是遇到写的复杂些的心里就打退堂鼓了. 最近在接手同事的代码时,有一些很长的pytho ...

  2. ConcurrentHashMap源码解析 JDK8

    一.简介 上篇文章详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理. 首先在看本文之前,希望对HashMap有一个详细的了解.不然看直接看Concur ...

  3. JDK1.7 ConcurrentHashMap 源码浅析

    概述 ConcurrentHashMap是HashMap的线程安全版本,使用了分段加锁的方案,在高并发时有比较好的性能. 本文分析JDK1.7中ConcurrentHashMap的实现. 正文 Con ...

  4. 并发-ConcurrentHashMap源码分析

    ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...

  5. ConcurrentHashMap源码走读

    目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 ConcurrentHashMap源码走读 简介 在从JDK8开始,为了提高并发度,Con ...

  6. Java之ConcurrentHashMap源码解析

    ConcurrentHashMap源码解析 目录 ConcurrentHashMap源码解析 jdk8之前的实现原理 jdk8的实现原理 变量解释 初始化 初始化table put操作 hash算法 ...

  7. Hashtable、ConcurrentHashMap源码分析

    Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角 ...

  8. ConcurrentHashMap源码分析(一)

    本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...

  9. ConcurrentHashMap 源码分析

    ConcurrentHashMap 源码分析 1. 前言    终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...

随机推荐

  1. 【代码学习】PYHTON 元组

    Python的元组与列表类似,不同之处在于元组的元素不能修改.也可进行分片 和 连接操作. 元组使用小括号,列表使用方括号. 一.访问元组 #coding=utf-8 Tuple = ('name', ...

  2. 解决前端项目启动时报错:Use // eslint-disable-next-line to ignore the next line.

    首先说一下这个问题产生的原因: 项目创建时设置了使用 eslint 进行代码规范检查. 解决办法: 找到webpack.base.conf.js文件,并且将下满这行代码注释掉. ...(config. ...

  3. base64相关

    1.base64指定的64个字符(包含52个大小写.10个数字和+./): abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ...

  4. YUM方式安装LAMP

    本文介绍两种方法yum安装LAMP, 方法1: 通过httpd的php模块方式安装LAMP 方法2: 通过php-fpm方式安装LAMP 安装环境:CentOS Linux release 7.5.1 ...

  5. 3000 - No Mycat Database selected

    今天在linux上搭建好mycat后,用Navicat连接出现如下错误 尝试很多方式发现并没有什么用,后面改用SQLyog连接就可以正常使用了!!!

  6. 用java代码打印九九乘法表

    package com.wf; public class cal { public static void main(String[] args) { for(int i=1;i<10;i++) ...

  7. python字符串操作方法详解

      字符串 字符串序列用于表示和存储文本,python中字符串是不可变对象.字符串是一个有序的字符的集合,用于存储和表示基本的文本信息,一对单,双或三引号中间包含的内容称之为字符串.其中三引号可以由多 ...

  8. mybatis=<>的写法

    第一种写法(1): 原符号 < <= > >= & ' "替换符号 < <= > >= & &apos; " ...

  9. 下载安装charles并导入证书、使用

    抓包原理 1.截获真实客户端的 HTTPS请求,伪装客户端向真实服务端发送 HTTPS 请求. 2.接受真实服务器响应,用 Charles 自己证书伪装服务端向真实客户端发送内容 3.证书导入 看博客 ...

  10. 三种方式安装mariadb-10.3.18

    安装环境:CentOS Linux release 7.5.1804 (Core) 一.yum安装 官方网站yum配置方法链接:https://mariadb.com/kb/en/library/yu ...