synchronized的锁升级/锁膨胀
偏向锁
偏向第一个拿到锁的线程。
即第一个拿到锁的线程,锁会在对象头 Mark Word 中通过 CAS 记录该线程 ID,该线程以后每次拿锁时都不需要进行 CAS(指轻量级锁)。
如果该线程正在执行同步代码块时有其他线程在竞争(指其他线程尝试 CAS 让 Mark Word 设置自己的线程 ID),会被升级为轻量级锁。
如果其他线程发现 Mark Word 里记的不是自己,且发现原持有偏向锁的线程已经执行完同步代码块,会尝试 CAS 把 Mark Word 中的改为自己的线程 ID。
轻量级锁
轻量级锁就是通过 CAS 进行加锁的。
JVM 会给线程的栈帧中创建一个叫锁记录 Lock Record 的空间,把对象头 Mark Word 复制到该空间里(Displaced Mark Word),并通过 CAS 尝试把原对象头 Mark Word 中锁记录指针指向该锁记录。如果成功,表示线程拿到了锁。如果失败,则进行自旋(自旋锁),自旋超过一定次数时升级为重量级锁,这时该线程会被内核挂起。
自旋锁
轻量级锁膨胀为重量级锁前,线程在执行 monitorenter 指令进入等待队列时,会通过自旋去尝试获得锁。
如果自旋超过一定次数时还未拿到锁,就会进入阻塞状态,等待内核来调度。此时会发生内核态与用户态之间的上下文切换,所以会影响性能(引入自旋锁就是为了减少这个开销)。
因为后面的线程也先进行自旋尝试获取锁,所以这对于已被阻塞的那些线程来说,会不公平。
重量级锁
重量级锁就是通过内核来操作线程。因为频繁出现内核态与用户态的切换,会严重影响性能。
升级为重量级锁时会在堆中创建 monitor 对象,并将 Mark Word 指向该 monitor 对象。monitor 中有 cxq(ContentionList),EntryList ,WaitSet,owner:
锁升级的流程图
图片来自:Java Synchronised机制
锁降级
Hotspot 在 1.8 开始有了锁降级。在 STW 期间 JVM 进入安全点时如果发现有闲置的 monitor(重量级锁对象),会进行锁降级。
为什么锁信息存放在对象头里?
因为在Java中任意对象都可以用作锁,因此必定要有一个映射关系,存储该对象以及其对应的锁信息(比如当前哪个线程持有锁,哪些线程在等待)。一种很直观的方法是,用一个全局map,来存储这个映射关系,但这样会有一些问题:需要对map做线程安全保障,不同的
synchronized
之间会相互影响,性能差;另外当同步对象较多时,该map可能会占用比较多的内存。所以最好的办法是将这个映射关系存储在对象头中,因为对象头本身也有一些hashcode、GC相关的数据,所以如果能将锁信息与这些信息共存在对象头中就好了。
也就是说,如果用一个全局 map 来存对象的锁信息,还需要对该 map 做线程安全处理,不同的锁之间会有影响。所以直接存到对象头。
其他文章
【死磕Java并发】—–深入分析synchronized的实现原理
【死磕 Java 并发】—– synchronized 的锁膨胀过程
【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference
synchronized的锁升级/锁膨胀的更多相关文章
- Synchronized锁升级
Synchronized锁升级 锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态(级别从低到高) 为什么要引入偏向锁? 因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞 ...
- Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级
原文链接:https://blog.csdn.net/tongdanping/article/details/79647337 1.锁升级锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态 ...
- 锁升级(Lock Escalations)——它们经常发生么?
前段时间,我写了一些SQL Server里锁升级的基础知识,还有它是如何影响执行计划的.今天,我想进一步谈下锁升级: 锁升级什么时候发生? 通常在SQL Server里如果在SQL语句里你请求的行数超 ...
- 如何解决 SQL Server 中的锁升级所致的阻塞问题
概要 锁升级为表锁插入转换很多细粒度的锁 (如行或页锁) 的过程.Microsoft SQL Server 动态确定何时执行锁升级.作出决定之前,SQL Server 将特定的扫描,整个事务,并且用于 ...
- synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析
警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...
- java架构之路(多线程)synchronized详解以及锁的膨胀升级过程
上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...
- Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)
不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...
- 并发编程:synchronized 锁升级过程的验证
关于synchronized关键字以及偏向锁.轻量级锁.重量级锁的介绍广大网友已经给出了太多文章和例子,这里就不再重复了,也可点击链接来回顾一下.在这里来实战操作一把,验证JVM是怎么一步一步 ...
- 深入并发锁,解析Synchronized锁升级
这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作. ...
随机推荐
- 洛谷P3237 [HNOI2014]米特运输(树形dp)
解题报告 题干 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都. ...
- Error: error getting chaincode bytes: failed to calculate dependencies报错解决办法
Error: error getting chaincode bytes: failed to calculate dependencies: incomplete package: github.c ...
- Mysql基础(六):索引、数据库备份、锁和事务、慢查询优化、索引命中相关
目录 数据库05 /索引.数据库备份.锁和事务.慢查询优化.索引命中相关 1. 什么是索引 2. 索引的原理 3. 索引的数据结构(聚集索引.辅助索引) 4. 索引操作 5. 索引的两大类型hash与 ...
- scrapy 基础组件专题(八):scrapy-redis 框架分析
scrapy-redis简介 scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署. 有如下特征: 分布式爬取 您可以启动多个spider工 ...
- python 并发专题(七):Twisted相关函数以及实现
一.基础原理 二.基本函数 三.爬虫实现 四.web服务器与客户端实现
- 用前端姿势玩docker【三】基于nvm的前端环境构建技巧
前言 安装docker啥的就不说了,这里重点强调一下,docker的环境问题.本人的环境: 虚拟机centos => docker => NAT => container 因为需要不 ...
- educoder SML程序设计题线下编译环境搭建
背景 最近<串并行数据结构与算法设计>的老师在educoder上布置了一些SML程序设计题,虽然网站上有在线编译功能,但还是在线下编译调试方便,特记录编译环境过程如下(我用的GVIM,但N ...
- ToText Basic 语法和 Crystal 语法
本文转自http://www.softwelt.com/Know/KnowDetail-2236860.html ToText 和 CStr 是等价函数. 重载 ToText (x) ToText ( ...
- tensorflow对鸢尾花进行分类——人工智能入门篇
tensorflow之对鸢尾花进行分类 任务目标 对鸢尾花数据集分析 建立鸢尾花的模型 利用模型预测鸢尾花的类别 环境搭建 pycharm编辑器搭建python3.* 第三方库 tensorflow1 ...
- 关于Object.defineProperty
讲解大致会根据下图展开 本文部分参考了书籍<你不知道的javascript>上卷 对象的定义与赋值 经常使用的定义与赋值方法obj.prop =value或者obj['prop'] ...