JDK8中的ConcurrentHashMap源码
背景
上文JDK8中的HashMap源码写了HashMap,这次写ConcurrentHashMap
ConcurrentHashMap源码
- /**
- * Maps the specified key to the specified value in this table.
- * Neither the key nor the value can be null.
- *
- * <p>The value can be retrieved by calling the {@code get} method
- * with a key that is equal to the original key.
- *
- * @param key key with which the specified value is to be associated
- * @param value value to be associated with the specified key
- * @return the previous value associated with {@code key}, or
- * {@code null} if there was no mapping for {@code key}
- * @throws NullPointerException if the specified key or value is null
- */
- public V put(K key, V value) {
- return putVal(key, value, false);
- }
- /** Implementation for put and putIfAbsent */
- final V putVal(K key, V value, boolean onlyIfAbsent) {
- if (key == null || value == null) throw new NullPointerException();
- int hash = spread(key.hashCode());
- int binCount = 0;
- for (Node<K,V>[] tab = table;;) {
- Node<K,V> f; int n, i, fh;
- //tab为空,则初始化
- if (tab == null || (n = tab.length) == 0)
- tab = initTable();
- 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);
- else {
- V oldVal = null;
- synchronized (f) { //对该槽进行加锁
- if (tabAt(tab, i) == f) {
- if (fh >= 0) {
- binCount = 1;
- for (Node<K,V> e = f;; ++binCount) {
- K ek;
- if (e.hash == hash &&
- ((ek = e.key) == key ||
- (ek != null && key.equals(ek)))) {
- oldVal = e.val;
- if (!onlyIfAbsent)
- e.val = value;
- break;
- }
- Node<K,V> pred = e;
- if ((e = e.next) == null) {
- pred.next = new Node<K,V>(hash, key,
- value, null);
- break;
- }
- }
- }
- else if (f instanceof TreeBin) {
- Node<K,V> p;
- binCount = 2;
- if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
- value)) != null) {
- oldVal = p.val;
- if (!onlyIfAbsent)
- p.val = value;
- }
- }
- }
- }
- if (binCount != 0) {
- if (binCount >= TREEIFY_THRESHOLD)
- treeifyBin(tab, i);
- if (oldVal != null)
- return oldVal;
- break;
- }
- }
- }
- addCount(1L, binCount);
- return null;
- }
- /**
- * Returns the value to which the specified key is mapped,
- * or {@code null} if this map contains no mapping for the key.
- *
- * <p>More formally, if this map contains a mapping from a key
- * {@code k} to a value {@code v} such that {@code key.equals(k)},
- * then this method returns {@code v}; otherwise it returns
- * {@code null}. (There can be at most one such mapping.)
- *
- * @throws NullPointerException if the specified key is null
- */
- public V get(Object key) {
- Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
- //获得hash值
- int h = spread(key.hashCode());
- //表非空,且该处不为空
- if ((tab = table) != null && (n = tab.length) > 0 &&
- (e = tabAt(tab, (n - 1) & h)) != null) {
- if ((eh = e.hash) == h) { //判断第1个
- if ((ek = e.key) == key || (ek != null && key.equals(ek)))
- return e.val;
- }
- else if (eh < 0) //eh<0,找其他的
- return (p = e.find(h, key)) != null ? p.val : null;
- while ((e = e.next) != null) { //遍历
- if (e.hash == h &&
- ((ek = e.key) == key || (ek != null && key.equals(ek))))
- return e.val;
- }
- }
- return null;
- }
ConcurrentHashMap代码太多了,粘了好几次粘不上来。只粘几个方法吧。
阅后感
ConcurrentHashMap通过几个原子操作尽量减少加锁操作。
扩容部分没有看太明白,尤其时扩容时进行get操作。后续再继续学习。
JDK8中的ConcurrentHashMap源码的更多相关文章
- JDK8中的HashMap源码
背景 很久以前看过源码,但是猛一看总感觉挺难的,很少看下去.当时总感觉是水平不到.工作中也遇到一些想看源码的地方,但是遇到写的复杂些的心里就打退堂鼓了. 最近在接手同事的代码时,有一些很长的pytho ...
- ConcurrentHashMap源码解析 JDK8
一.简介 上篇文章详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理. 首先在看本文之前,希望对HashMap有一个详细的了解.不然看直接看Concur ...
- JDK1.7 ConcurrentHashMap 源码浅析
概述 ConcurrentHashMap是HashMap的线程安全版本,使用了分段加锁的方案,在高并发时有比较好的性能. 本文分析JDK1.7中ConcurrentHashMap的实现. 正文 Con ...
- 并发-ConcurrentHashMap源码分析
ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...
- ConcurrentHashMap源码走读
目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 ConcurrentHashMap源码走读 简介 在从JDK8开始,为了提高并发度,Con ...
- Java之ConcurrentHashMap源码解析
ConcurrentHashMap源码解析 目录 ConcurrentHashMap源码解析 jdk8之前的实现原理 jdk8的实现原理 变量解释 初始化 初始化table put操作 hash算法 ...
- Hashtable、ConcurrentHashMap源码分析
Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角 ...
- ConcurrentHashMap源码分析(一)
本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...
- ConcurrentHashMap 源码分析
ConcurrentHashMap 源码分析 1. 前言 终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...
随机推荐
- 【代码学习】PYHTON 元组
Python的元组与列表类似,不同之处在于元组的元素不能修改.也可进行分片 和 连接操作. 元组使用小括号,列表使用方括号. 一.访问元组 #coding=utf-8 Tuple = ('name', ...
- 解决前端项目启动时报错:Use // eslint-disable-next-line to ignore the next line.
首先说一下这个问题产生的原因: 项目创建时设置了使用 eslint 进行代码规范检查. 解决办法: 找到webpack.base.conf.js文件,并且将下满这行代码注释掉. ...(config. ...
- base64相关
1.base64指定的64个字符(包含52个大小写.10个数字和+./): abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ...
- YUM方式安装LAMP
本文介绍两种方法yum安装LAMP, 方法1: 通过httpd的php模块方式安装LAMP 方法2: 通过php-fpm方式安装LAMP 安装环境:CentOS Linux release 7.5.1 ...
- 3000 - No Mycat Database selected
今天在linux上搭建好mycat后,用Navicat连接出现如下错误 尝试很多方式发现并没有什么用,后面改用SQLyog连接就可以正常使用了!!!
- 用java代码打印九九乘法表
package com.wf; public class cal { public static void main(String[] args) { for(int i=1;i<10;i++) ...
- python字符串操作方法详解
字符串 字符串序列用于表示和存储文本,python中字符串是不可变对象.字符串是一个有序的字符的集合,用于存储和表示基本的文本信息,一对单,双或三引号中间包含的内容称之为字符串.其中三引号可以由多 ...
- mybatis=<>的写法
第一种写法(1): 原符号 < <= > >= & ' "替换符号 < <= > >= & ' " ...
- 下载安装charles并导入证书、使用
抓包原理 1.截获真实客户端的 HTTPS请求,伪装客户端向真实服务端发送 HTTPS 请求. 2.接受真实服务器响应,用 Charles 自己证书伪装服务端向真实客户端发送内容 3.证书导入 看博客 ...
- 三种方式安装mariadb-10.3.18
安装环境:CentOS Linux release 7.5.1804 (Core) 一.yum安装 官方网站yum配置方法链接:https://mariadb.com/kb/en/library/yu ...