java锁升级过程

java锁升级过程java中对象锁有4种状态:(级别从低到高)1.无锁状态2.偏向锁状态3.轻量级锁状态4.重量级锁状态对象头分两部分信息,第一部分用于存储哈希码、GC分代年龄等,这部分数据被称为”MarkWord”。在32位的HotSpot虚拟机中对象未被锁定的状态下,MarkWord的32bit空间中的25bit用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固…

大家好,又见面了,我是你们的朋友全栈君。

java中对象锁有4种状态:(级别从低到高)
1.无锁状态
2.偏向锁状态
3.轻量级锁状态
4.重量级锁状态

对象头分两部分信息,第一部分用于存储哈希码、GC分代年龄等,这部分数据被称为”Mark Word”。在32位的HotSpot虚拟机中对象未被锁定的状态下,Mark Word的32bit空间中的25bit用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0,在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容见下表:
在这里插入图片描述
锁升级的方向是:无锁——>偏向锁——>轻量级锁——>重量级锁,并且膨胀方向不可逆。

1.偏向锁
偏向锁是JDK6中引入的一项锁优化,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。
偏向锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要同步。

2.轻量级锁
如果明显存在其它线程申请锁,那么偏向锁将很快升级为轻量级锁。

3.自旋锁
自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

4.重量级锁
指的是原始的Synchronized的实现,重量级锁的特点:其他线程试图获取锁时,都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程。

锁升级场景:

场景1: 程序不会有锁的竞争。
那么这种情况我们不需要加锁,所以这种情况下对象锁状态为无锁。

场景2: 经常只有某一个线程来加锁。
加锁过程:也许获取锁的经常为同一个线程,这种情况下为了避免加锁造成的性能开销,所以并不会加实际意义上的锁,偏向锁的执行流程如下:
1、线程首先检查该对象头的线程ID是否为当前线程;
2、A:如果对象头的线程ID和当前线程ID一直,则直接执行代码;B:如果不是当前线程ID则使用CAS方式替换对象头中的线程ID,如果使用CAS替换不成功则说明有线程正在执行,存在锁的竞争,这时需要撤销偏向锁,升级为轻量级锁。
3、如果CAS替换成功,则把对象头的线程ID改为自己的线程ID,然后执行代码。
4、执行代码完成之后释放锁,把对象头的线程ID修改为空。

场景3: 有线程来参与锁的竞争,但是获取锁的冲突时间很短。
当开始有锁的冲突了,那么偏向锁就会升级到轻量级锁;线程获取锁出现冲突时,线程必须做出决定是继续在这里等,还是回家等别人打电话通知,而轻量级锁的路基就是采用继续在这里等的方式,当发现有锁冲突,线程首先会使用自旋的方式循环在这里获取锁,因为使用自旋的方式非常消耗CPU,当一定时间内通过自旋的方式无法获取到锁的话,那么锁就开始升级为重量级锁了。

场景4: 有大量的线程参与锁的竞争,冲突性很高。
我们知道当获取锁冲突多,时间越长的时候,我们的线程肯定无法继续在这里死等了,所以只好先休息,然后等前面获取锁的线程释放了锁之后再开启下一轮的锁竞争,而这种形式就是我们的重量级锁。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161185.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux目录结构详解_文件系统目录结构采用

    linux目录结构详解_文件系统目录结构采用前言平常linux系统用的也不少,那么linux下的每个目录都是用来干什么的,小伙伴们有仔细研究过吗?让我们来了解下吧Linux系统目录结构登录系统后,在当前命令窗口下输入命令:[root@

    2022年7月31日
    3
  • 分布式事务TCC方案Hmily——springcloud + feign + mybatis

    分布式事务TCC方案Hmily——springcloud + feign + mybatisTCC理论:分布式事务基础理论——TCCHmily介绍:分布式事务TCC方案——Hmily金融级柔性分布式事务解决方案介绍本文demo代码:GitHub依赖<dependency><groupId>org.dromara</groupId><artifactId>hmily-springcloud</artifactId><vers

    2022年5月13日
    69
  • 事件TransactionScope

    事件TransactionScopeusing(TransactionScopescope=newTransactionScope()){ scope.Complete();}只需要把需要事务包裹的逻辑块写在using(TransactionScopets=newTransactionScope())中就可以了。从这种写法可以看出,TransactionScope实现了IDispose接口。除…

    2022年7月24日
    4
  • 怎么提高开车技术_全日行车计划

    怎么提高开车技术_全日行车计划Description现在有n个城市,每个城市有它的高度HiH_i,保证每个HiH_i互不相同。我们定义两个城市之间的距离disi,j=|Hi−Hj|dis_{i,j}=|H_i-H_j|,并且只能从编号小的城市去到编号大的城市。现在有两个人,小A和小B要开车(雾)去旅行。小A先开一天,小B再开一天。每一天都可以从一个开到另一个城市。小A会选择去离当前城市第二近的城市,小B会选择去离当前城市最近的那

    2022年8月22日
    3
  • PHP审计之PHP反序列化漏洞

    PHP审计之PHP反序列化漏洞前言一直不懂,PHP反序列化感觉上比Java的反序列化难上不少。但归根结底还是serialize和unserialize中的一些问题。在此不做多的介绍。魔术方法

    2021年12月13日
    40
  • sqlsession、sqlsessionManager以及sqlsessionTemplate的理解

    sqlsession、sqlsessionManager以及sqlsessionTemplate的理解sqlSession是mybatis的核心操作类,其中对数据库的crud都封装在这个中,是一个顶级接口,其中默认实现类是DefaultSqlSession这个类,为什么说DefaultSqlsession不是线程安全的?首先我们都知道mybatis在底层都是使用的JDBC,而JDBC这本来就是线程不安全的(连接对象Connection只有一个),所以我们只要关注session和co…

    2022年5月8日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号