重量级锁、自旋锁、自适应自旋锁、轻量级锁、偏向锁、可重入锁、互斥锁/排他锁/独占锁

重量级锁

获取不到锁就立刻进入阻塞状态的锁是重量级锁。

轻量级锁

当另一个线程参与到偏向锁竞争时,会先判断 markword 中保存的线程 ID 是否与这个线程 ID 相等,如果不相等,会立即撤销偏向锁,升级为轻量级锁。每个线程在自己的线程栈中生成一个 LockRecord ( LR ),然后每个线程通过 CAS (自旋 )的操作将锁对象头中的 markwork 设置为指向自己的 LR 的指针,哪个线程设置成功,就意味着获得锁。 关于 synchronized 中此时执行的 CAS 操作是通过HotSpot 中 bytecodeInterpreter.cpp 文件 C++ 代码实现的。

如果真的遇到了竞争,我们就会认为轻量级锁已经不适合了,我们就会把轻量级锁升级为重量级锁了。

所以轻量级锁适合用在那种,很少出现多个线程竞争一个锁的情况,也就是说,适合那种多个线程总是错开时间来获取锁的情况。

自旋锁

自旋锁是JDK1.4.2的时候引入的, 默认为关闭状态, 可以使用-XX:+UseSpinning参数来开启 ,可以用-XX:PreBlockSpin 来控制自旋多少次, 默认是10次。

自适应自旋锁

JDK 6中对自旋锁的优化,引入了自适应的自旋。

自适应意味着自旋的时间不再是固定的了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的。

如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而允许自旋等待持续相对更长次数。

另一方面,如果对于某个锁,自旋很少成功获得过锁,那么自旋次数少,以避免浪费处理器资源。

有了自适应自旋,随着程序运行时间的增长及性能监控信息的不断完善,虚拟机对程序锁的状况预测就会越来越精准,虚拟机就会变得越来越“聪明”了。

偏向锁

偏向锁退出时不改变对象头中是偏向锁的标记,也不删除记录的线程ID,什么操作都没有,直接退出。

偏向锁升级:https://blog.csdn.net/haoranhaoshi/article/details/108530134

JDK1.8偏向锁默认不开启。开启方式:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0。关闭方式:-XX:-UseBiasedLocking。

开启偏向锁后,如果执行监视对象的hashCode()方法后导致对象头种不能存储线程ID,就会锁升级。

偏向锁适用于那种,始终只有一个线程在执行一个方法的情况。

可重入锁

synchronized 拥有强制原子性的内部锁机制,是一把可重入锁。因此,在一个线程使用 synchronized 方法时调用该对象另一个 synchronized 方法,即一个线程得到一个对象锁后再次请求该对象锁,是永远可以拿到锁的。在 Java 中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。synchronized 锁的对象头的 markwork 中会记录该锁的线程持有者和计数器,当一个线程请求成功后, JVM 会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个 synchronized 方法/块时,计数器会递减,如果计数器为 0 则释放该锁。

互斥锁/排他锁/独占锁

synchronized 是一把互斥锁/排他锁/独占锁,当前线程如果获取到锁,会导致其他线程无法获取到锁。

总结

偏向锁、轻量级锁、重量级锁的差异在于线程获取不到锁的策略:

偏向锁会升级为轻量级锁,轻量级锁会自旋或自适应自旋,重量级锁会使线程阻塞。

自旋锁、自适应自旋锁关注的是获取不到锁时不阻塞,不升级的策略。不关注加的锁是偏向锁、轻量级锁还是重量级锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
无状态偏向、轻量级量级都是Java中的机制,它们的实现方式和性能表现不同。 无状态:也称为自,当线程尝试获取时,如果已经被其他线程占用,该线程会一直自等待的释放,直到获取到为止。这种适用于的持有时间非常短的情况,因为长时间的自会浪费CPU资源。 偏向偏向是一种针对加操作的优化手段,它的目标是减少无竞争情况下的操作的性能消耗。当一个线程访问一个偏向时,它会将对象头中的标识位设置为偏向,并将线程ID记录在对象头中。之后,该线程再次请求时,无需再次竞争,直接获取即可。这种适用于只有一个线程访问对象的情况。 轻量级:轻量级是一种针对多线程竞争情况下的优化手段,它的目标是减少线程阻塞的时间,提高程序的并发性能。当一个线程访问一个轻量级时,它会将对象头中的标识位设置为轻量级,并将对象的指针保存在线程的栈帧中。之后,其他线程再次请求时,会通过自的方式尝试获取,而不是阻塞等待。如果自失败,就会升级为量级。这种适用于的竞争不是很激烈的情况。 量级量级是一种针对多线程竞争情况下的优化手段,它的目标是保证线程的正确性和程序的稳定性。当一个线程访问一个量级时,它会进阻塞状态,直到被释放。这种适用于的竞争非常激烈的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值