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. 前言 终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...
随机推荐
- Codeforce 977E Cyclic Components
dfs判断图的连通块数量~ #include<cstdio> #include<algorithm> #include<vector> #include<cs ...
- Mybatis中mapper.xml的使用
详解多对多,mybatis多对多查询(xml方式和注解方式) 链接:https://blog.csdn.net/qq_42524262/article/details/98383977 链接:http ...
- Vue——手机号、验证码登录(设置按钮60s禁用倒计时)
最近在做一个Vue项目,前端通过手机号.验证码登录,获取验证码按钮需要设置60s倒计时(点击一次后,一分钟内不得再次点击).先看一下效果图: 输入正确格式的手机号码后,“获取验证码”按钮方可点击:点击 ...
- Codeforces Round #611 (Div. 3) C
There are nn friends who want to give gifts for the New Year to each other. Each friend should give ...
- 前端学习 之 CSS(一)
一:什么是 CSS? ·CSS 指层叠样式表 (Cascading Style Sheets) ·样式定义如何显示 HTML 元素 ·样式通常存储在样式表中 ·把样式添加到 HTML 4.0 中,是为 ...
- 到头来还是逃不开Java - Java13面向对象基础
面向对象基础 没有特殊说明,我的所有学习笔记都是从廖老师那里摘抄过来的,侵删 引言 兜兜转转到了大四,学过了C,C++,C#,Java,Python,学一门丢一门,到了最后还是要把Java捡起来.所以 ...
- Navicat Premium 12安装及激活
一.安装 百度云下载地址:https://pan.baidu.com/s/1T5BjpBqLtwCy26szcKSdKw 提取码:ujzx 二.激活步骤 ①将navicat-keygen-for-x6 ...
- UICollectionViewCell点击高亮效果(附带效果GIF)
首先效果如下: 背景是这样的:UI上使用的是UICollectionView,所以后面会使用它的协议方法完成. 实现思路是这样的:高亮状态+点击后短时间内保持颜色变化 实现的代码参考如下: // Ce ...
- vue element 表单多个验证时,滚动到验证提示的位置
最近项目有个下单的过程,需要输入很多信息,每次提交都要往下滑,还要去验证,测试后发现体验也不好,element框架也没提供这种滚动方法, 不过提供了一个验证的方法 validate (两个参数:是否校 ...
- P1025数的划分
P1025数的划分 #include <iostream> using namespace std; int n,k; int cnt; void dfs(int s,int step,i ...