偏向锁的几种状态

偏向锁是一种优化策略,旨在减少轻量级锁的CAS操作。当只有一个线程访问对象时,它会将对象头的Mark Word设置为线程ID,后续此线程重入时不需CAS。在调用对象的hashCode()方法或出现锁竞争时,偏向锁会被撤销,可能升级为轻量级锁。对象创建后,默认开启偏向锁,但可通过虚拟机参数禁用延迟。撤销偏向锁可能通过其他线程使用对象或特定线程同步操作触发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

偏向锁不会主动释放锁

1.定义

在轻量级的锁中,我们可以发现,如果同一个线程对同一个对象进行重入锁时,也需要执行CAS操作,这是有点耗时滴,那么java6开始引入了偏向锁的东东,只有第一次使用CAS时将对象的Mark Word头设置为入锁线程ID,之后这个入锁线程再进行重入锁时,发现线程ID是自己的,那么就不用再进行CAS了

2. 偏向状态

 

2.1一个对象的创建过程

  1. 如果开启了偏向锁(默认是开启的),那么对象刚创建之后,Mark Word 最后三位的值101,并且这是它的Thread,epoch,age都是0,在加锁的时候进行设置这些的值.

  2. 偏向锁默认是延迟的,不会在程序启动的时候立刻生效,如果想避免延迟,可以添加虚拟机参数来禁用延迟:-XX:BiasedLockingStartupDelay=0来禁用延迟

  3. 注意:处于偏向锁的对象解锁后,线程 id 仍存储于对象头中

  4. 最后三位如果是000说明是轻量级锁,如果是101是偏向锁,如果是001是偏向锁失效 

3撤销偏向锁

3.1使用hashcode()方法

当调用对象的hashcode方法的时候就会撤销这个对象的偏向锁,因为使用偏向锁时没有位置存hashcode的值了

 3.2其它线程使用对象

偏向锁撤销变成轻量级锁的过程,那么就得满足轻量级锁的使用条件,就是没有线程对同一个对象进行锁竞争,使用waitnotify 来辅助实现

一个线程在加锁之前先wait。另一个线程先使用锁,等待锁用完之后,调用notify唤醒正在wait的线程,使得两个线程分开始用锁,在第二个线程使用锁前的时候,先是偏向第一个线程的(101),在使用锁的时偏向锁就失效了,转化为了000(轻量级锁),使用锁之后,输出的最后三位是001(偏向锁失效的状态)

4批量重偏向

如果对象被多个线程访问,但是没有竞争,这时候偏向了线程一的对象又有机会重新偏向线程二,即可以不用升级为轻量级锁,可这和我们之前做的实验矛盾了呀,其实要实现重新偏向是要有条件的:就是超过20对象对同一个线程如线程一撤销偏向时,那么第20个及以后的对象才可以将撤销对线程一的偏向这个动作变为将第20个及以后的对象偏向线程二

当撤销偏向阈值超过40次后, jvm会这样觉得,自己确实偏向错了,根本就不该偏向,于是整个类的所有对象都会变为不可偏向的,新建的对象也是不可偏向的 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值