java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock

2023-05-16

原文地址:https://cloud.tencent.com/developer/article/1509556

今天突然被一个同事问到java8为何放弃分段锁,于是花了点时间针对这个问题进行了小小的总结。

jdk1.7分段锁的实现

和hashmap一样,在jdk1.7中ConcurrentHashMap的底层数据结构是数组加链表。和hashmap不同的是ConcurrentHashMap中存放的数据是一段段的,即由多个Segment(段)组成的。每个Segment中都有着类似于数组加链表的结构。

关于Segment

ConcurrentHashMap有3个参数:

  1. initialCapacity:初始总容量,默认16
  2. loadFactor:加载因子,默认0.75
  3. concurrencyLevel:并发级别,默认16

其中并发级别控制了Segment的个数,在一个ConcurrentHashMap创建后Segment的个数是不能变的,扩容过程过改变的是每个Segment的大小。

关于分段锁

段Segment继承了重入锁ReentrantLock,有了锁的功能,每个锁控制的是一段,当每个Segment越来越大时,锁的粒度就变得有些大了。

  • 分段锁的优势在于保证在操作不同段 map 的时候可以并发执行,操作同段 map 的时候,进行锁的竞争和等待。这相对于直接对整个map同步synchronized是有优势的。
  • 缺点在于分成很多段时会比较浪费内存空间(不连续,碎片化); 操作map时竞争同一个分段锁的概率非常小时,分段锁反而会造成更新等操作的长时间等待; 当某个段很大时,分段锁的性能会下降。

jdk1.8的map实现

和hashmap一样,jdk 1.8中ConcurrentHashmap采用的底层数据结构为数组+链表+红黑树的形式。数组可以扩容,链表可以转化为红黑树。

什么时候扩容?

  1. 当前容量超过阈值
  2. 当链表中元素个数超过默认设定(8个),当数组的大小还未超过64的时候,此时进行数组的扩容,如果超过则将链表转化成红黑树

什么时候链表转化为红黑树?

当数组大小已经超过64并且链表中的元素个数超过默认设定(8个)时,将链表转化为红黑树

ConcurrentHashMap的put操作代码如下:

把数组中的每个元素看成一个桶。可以看到大部分都是CAS操作,加锁的部分是对桶的头节点进行加锁,锁粒度很小。

为什么不用ReentrantLock而用synchronized ?

  • 减少内存开销:如果使用ReentrantLock则需要节点继承AQS来获得同步支持,增加内存开销,而1.8中只有头节点需要进行同步。
  • 内部优化:synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock 的相关文章

随机推荐

  • Android 项目中 Mopub 广告基础使用(插屏和横幅)

    1 下载 MoPub Android SDK repositories mavenCentral MoPub SDK is now available in Maven Central android compileOptions sour
  • Camera2打开相机,建立会话,并监听相机流(以拍照为例)

    Camera2打开相机 xff0c 建立会话 xff0c 并监听相机流 xff08 以拍照为例 xff09 获取 CameraManager通过 CameraManager openCamera 方法打开相机 xff0c 监听回调 xff0
  • 协程的创建

    GlobalScope launch 使用 xff08 代码会在当前线程所有内容执行完成之后再执行 xff09 新建线程 xff0c 执行 34 延时 1 秒 xff0c 打印当前线程名称 34 的代码 GlobalScope launch
  • Retrofit 使用

    Retrofit 使用 Retrofit 官网导入依赖库请求数据 xff08 以 玩Android 为例 xff0c 官方文档为 github 接口 xff1a https api github com xff09 数据请求前提getpos
  • Retrofit2 源码分析

    Retrofit2 源码分析 整体流程 xff08 以异步请求为例 xff09 源码分析总结 整体流程 xff08 以异步请求为例 xff09 通过建造者模式创建 Retrofit 对象Retrofit 对象通过 create 方法 xff
  • jar文件双击不能打开

    注册表 在Windows开始菜单的搜索框中输入 regedit xff0c 在上方搜索出的文件regedit上点击鼠标右键 xff0c 在弹出的菜单中选择 以管理员身份运行 在注册表编辑器中 xff0c 找到 HKEY CLASSES RO
  • 深入理解JS中的变量作用域

    在 JS 当中一个变量的作用域 xff08 scope xff09 是程序中定义这个变量的区域 变量分为两类 xff1a 全局 xff08 global xff09 的和局部的 其中全局变量的作用域是全局性的 xff0c 即在 JavaSc
  • SystemUI返回键手势和launcher上滑手势

    背景描述 最近修改bug和需求 xff0c 接触到系统手势这一块 xff0c 发现是一个薄弱点 xff0c 以前只是简单知道 xff0c 没有深入了解 手势这一块涉及的模块和流程比较多 xff0c 记录一下别人写的比较好的文章参考一下 初步
  • Android Studio 展开、折叠代码块快捷键

    展开 折叠代码块的方法 xff1a 折叠单个方法 xff1a 34 ctrl 34 43 34 34 展开单个方法 xff1a 34 ctrl 34 43 34 43 34 折叠全部方法 xff1a 34 ctrl 34 43 34 shi
  • Android Studio 重写父类方法的快捷键

    快速重写父类方法的快捷键 xff1a ctrl 43 o
  • 门面(外观)模式和代理模式区别

    本文只讲门面模式和代理模式的区别 今天用旅游吃饭来区分下门面模式和代理模式 门面模式是给用户提供一种服务 xff0c 就相当于我们的饭店 xff0c 可以给顾客提供美味的食物 代理模式是根据用户的需求 xff0c 提供解决该需求的方案 xf
  • 传输层TCP的流量控制和拥塞控制(图文详解)

    TCP的流量控制和拥塞控制 TCP流量控制流量控制中的死锁问题 x1f512 持续计时器 TCP的拥塞控制增加资源能解决拥塞吗 xff1f 拥塞往往会趋于恶化拥塞控制方法慢开始和拥塞避免慢开始拥塞避免 快重传和快恢复快重传快恢复 TCP流量
  • 数据链路层的子层MAC层(图文详解)

    数据链路层的子层MAC层 MAC层MAC层的硬件地址单站地址 xff0c 组地址 xff0c 广播地址全球管理与本地管理适配器检查MAC地址 MAC帧的格式 MAC层 MAC不是物理层 xff01 MAC不是物理层 xff01 MAC不是物
  • 补码一位乘法(Booth算法)和补码二位乘法详解

    文章目录 补码一位乘法补码二位乘法布斯算法的硬件实现 A D Booth提出了一种算法 xff1a 相乘二数用补码表示 xff0c 它们的符号位与数值为一起参与乘法运算的过程 xff0c 直接得出用补码表示的乘法结果 xff0c 且正数和负
  • 计算机原理中的字,位扩展,都给老子进来学,看不懂算我输!

    文章目录 涉及到的几个概念地址线与数据线 字扩展与位扩展 涉及到的几个概念 MDR xff1a 数据寄存器 xff0c 用来存入内存中读入 写出的信息 MAR xff1a 地址寄存器 xff0c 用来存放当前CPU访问的内存单元地址 地址线
  • 计算机组成原理中指令的四个工作周期

    文章目录 执行过程取指周期带有间址寻址的指令周期带有中断的指令周期 间指周期执行周期中断周期 执行过程 执行过程 xff1a 在取址周期后 xff0c 需要判断是否有间址周期 xff0c 如果没有就进入到了执行周期 xff0c 在执行周期过
  • Uncaught TypeError: $(...).modal is not a function

    项目场景 xff1a ssm框架配合bootstrap和AJAX xff0c 点击按钮弹出模态框 问题描述 xff1a Uncaught TypeError modal is not a function 原因分析 xff1a 没有引入bo
  • Lock锁及获取锁的四种方法

    为什么使用LOCK xff1f LOCK锁LOCK锁的上锁与解锁 为什么使用LOCK xff1f 传统的Synchronized锁有非常多的缺点 xff1a 锁的唤醒和阻塞代价较高 xff0c 线程的阻塞和唤醒 xff0c 操作系统需要在用
  • Chrome浏览器无法安装插件的解决办法

    国内不翻墙情况下 xff0c 无法正常登录谷歌账户 无法访问谷歌应用商店 xff0c 无法同步个人数据和安装使用各类插件 本文解决方法 xff1a 开发模式安装 步骤 xff1a 1 将xxx crx插件的扩展名改成 zip或者 rar并解
  • java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock

    原文地址 xff1a https cloud tencent com developer article 1509556 今天突然被一个同事问到java8为何放弃分段锁 xff0c 于是花了点时间针对这个问题进行了小小的总结 jdk1 7分