java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock
原文地址:https://cloud.tencent.com/developer/article/1509556
推荐一篇 ConcurrentHashMap 和 HashMap 写的比较的的文章
jdk1.7分段锁的实现
和hashmap一样,在jdk1.7中ConcurrentHashMap的底层数据结构是数组加链表。和hashmap不同的是ConcurrentHashMap中存放的数据是一段段的,即由多个Segment(段)组成的。每个Segment中都有着类似于数组加链表的结构。
关于Segment
ConcurrentHashMap有3个参数:
- initialCapacity:初始总容量,默认16
- loadFactor:加载因子,默认0.75
- concurrencyLevel:并发级别,默认16
其中并发级别控制了Segment的个数,在一个ConcurrentHashMap创建后Segment的个数是不能变的,扩容过程过改变的是每个Segment的大小。
关于分段锁
段Segment继承了重入锁ReentrantLock,有了锁的功能,每个锁控制的是一段,当每个Segment越来越大时,锁的粒度就变得有些大了。
- 分段锁的优势在于保证在操作不同段 map 的时候可以并发执行,操作同段 map 的时候,进行锁的竞争和等待。这相对于直接对整个map同步synchronized是有优势的。
- 缺点在于分成很多段时会比较浪费内存空间(不连续,碎片化); 操作map时竞争同一个分段锁的概率非常小时,分段锁反而会造成更新等操作的长时间等待; 当某个段很大时,分段锁的性能会下降。
jdk1.8的map实现
和hashmap一样,jdk 1.8中ConcurrentHashmap采用的底层数据结构为数组+链表+红黑树的形式。数组可以扩容,链表可以转化为红黑树。
什么时候扩容?
- 当前容量超过阈值
- 当链表中元素个数超过默认设定(8个),当数组的大小还未超过64的时候,此时进行数组的扩容,如果超过则将链表转化成红黑树
什么时候链表转化为红黑树?
当数组大小已经超过64并且链表中的元素个数超过默认设定(8个)时,将链表转化为红黑树
ConcurrentHashMap的put操作代码如下:

把数组中的每个元素看成一个桶。可以看到大部分都是CAS操作,加锁的部分是对桶的头节点进行加锁,锁粒度很小。
为什么不用ReentrantLock而用synchronized ?
- 减少内存开销:如果使用ReentrantLock则需要节点继承AQS来获得同步支持,增加内存开销,而1.8中只有头节点需要进行同步。
- 内部优化:synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。
总结:
参考
- https://my.oschina.net/pingpangkuangmo/blog/817973
- https://www.wanaright.com/2018/09/30/java10-concurrenthashmap-no-segment-lock/
- https://blog.csdn.net/mian_csdn/article/details/70185104
- https://cloud.tencent.com/developer/article/1509556
原文地址:https://cloud.tencent.com/developer/article/1509556
如有侵权,留言删除
java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock的更多相关文章
- ConcurrentHashMap 1.8为什么要使用CAS+Synchronized取代Segment+ReentrantLock
大家应该都知道ConcurrentHashMap在1.8的时候有了很大的改动,当然,我这里要说的改动不是指链表长度大于8就转为红黑树这种常识,我要说的是ConcurrentHashMap在1.8为什么 ...
- JDK8的 CHM 为何放弃分段锁
概述 我们知道, 在 Java 5 之后,JDK 引入了 java.util.concurrent 并发包 ,其中最常用的就是 ConcurrentHashMap 了, 它的原理是引用了内部的 Seg ...
- 分段锁——ConcurrentHashMap
1.线程不安全的HashMap因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap. 2.效率低下的HashTable容 ...
- java8中ConcurrentHashMap
HashMap的线程不安全主要体现在resize时的死循环及使用迭代器时的fast-fail上. Fast-fail: fail-fast 机制是java集合(Collection)中的一种错误机制. ...
- Java8 中 ConcurrentHashMap工作原理的要点分析
简介: 本文主要介绍Java8中的并发容器ConcurrentHashMap的工作原理,和其它文章不同的是,本文重点分析了不同线程的各类并发操作如get,put,remove之间是如何同步的,以及这些 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...
- 学习ConcurrentHashMap1.7分段锁原理
1. 概述 接上一篇 学习 ConcurrentHashMap1.8 并发写机制, 本文主要学习 Segment分段锁 的实现原理. 虽然 JDK1.7 在生产环境已逐渐被 JDK1.8 替代,然而一 ...
- redis分布式锁扣减库存弊端: 吞吐量低, 解决方法:使用 分段锁 分布式分段锁并发扣减库存--代码实现
package tech.codestory.zookeeper.aalvcai.ConcurrentHashMapLock; import lombok.AllArgsConstructor; im ...
- 锁开销优化以及 CAS 简单说明
锁开销优化以及 CAS 简单说明 锁 互斥锁是用来保护一个临界区,即保护一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性.当有线程进入临界区段时,其他线程或是进程必须等待. 在 ...
随机推荐
- 前端html,css考点
1, 内联元素,块级元素相关知识点 参考链接:https://edu.aliyun.com/a/103378 (1)置换元素 概念:浏览器根据元素的标签和属性,来决定元素的具体显示内容.<img ...
- codewars--js--create phone number
Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of th ...
- kubernetes监控
总体设计思想 总体设计架构图Kubernetes monitoring architecture 设计介绍 监控分成两个部分 核心指标流程 包括的组件有 kubelet.resource estima ...
- Git操作:查看所有分支的提交修改
我们在廖雪峰Git教程或者一些书籍学习git分支时,大都会学习到这样一个命令git log --graph或者就是单纯的git log,他可以用来查看当前分支.但是这个弊端就是:它只能查看与当前分支有 ...
- Android在Activity中与Fragment中创建自定义菜单的区别
区别就在这里,Activity中添加菜单要这样: public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R ...
- MySql学习-3.命令脚本
一.数据库操作: 1. 登录数据库:mysql -uroot -p (这个password是自己设定的,我这里的没密码) 注意:(数据路径是:D:\MySql\install1\data 操作路径:D ...
- 高级UI组件(二)
1.图像视图 <ImageView android:id="@+id/imageView" android:layout_width="wrap_content&q ...
- (LNMP) Nginx_PHP_MariaDB
L用的是Centos7.5以上,主要是NMP三组件的安装记录. 通常会先安装一下依赖: yum install -y pcre-devel zlib-devel openssl-devel 使用yum ...
- matlab初探寻
matlab <iframe src="//player.bilibili.com/player.html?aid=74994893&cid=128293306&pag ...
- windows下安装openjdk
redhat版openjdk,解压后就能用,下载地址https://developers.redhat.com/products/openjdk/download. Azul Zulu版openjdk ...