1.6锁的升级过程

对象的HashCode是需要手动调用的,当没有调用时获取锁用的就是偏向锁,当调用完HashCode,就不在使用偏向锁,改为轻量级或者重量级锁,
wait方法会导致锁直接升级成重量级锁。



轻量级锁升级成重量级锁:

1、自旋锁尝试失败次数超过一定阈值(默认为5次),会升级为重量级锁。
2、同一个线程中,多次尝试获取同一个对象的锁,前一次获取锁的过程中,如果有其他线程尝试获取同一个对象的锁,则当前线程会一直自旋等待,
直到获取到锁或者等待时间超过一定的阈值(默认为500个时钟周期),此时会升级为重量级锁。

小结:2个条件,自选5次失败,或者等待500个时钟周期

1.6锁的升级过程_第1张图片

1.6锁的升级过程_第2张图片

一、偏向锁

1.6锁的升级过程_第3张图片
在这里插入图片描述

1.6锁的升级过程_第4张图片

轻量级锁

当有新的线程进来时
在这里插入图片描述

在这里插入图片描述
其实就是竞争不激烈,但是确实存在多个锁竞争的情况,而且是,大家都很有序的进行,一释放,下一个线程就拿到锁,很有顺序的获取锁,基本上通过自旋的方式代替了Sync… 本质是自旋CAS完成。

在这里插入图片描述
那自旋CAS什么时候会升级成为重量级锁。

重量级锁

轻量级锁升级为重量级锁的步骤如下:

当一个线程尝试获取一个已经被另一个线程持有的轻量级锁时,它会进入自旋等待。在这个过程中,它会不断地检查锁是否被释放。
如果自旋等待超过了预设的次数(即自旋阈值),JVM会认为线程之间的竞争非常激烈,因此决定将轻量级锁升级为重量级锁。这个过程是通过膨胀(inflate)操作实现的。
膨胀操作会将轻量级锁的标记位改为重量级锁的标记位,并将当前持有锁的线程的ID存储在对象头中。这个过程需要CAS(Compare-And-Swap)操作来保证原子性。
一旦膨胀操作完成,其他尝试获取该锁的线程将被阻塞并放入锁的等待队列中。此时,锁的竞争已经变得非常激烈,因此需要使用更重的锁策略来确保线程安全。
重量级锁的释放过程相对复杂。当持有锁的线程释放锁时,它会唤醒等待队列中的一个线程来竞争该锁。这个过程涉及到线程的挂起和唤醒操作,因此开销较大。

1、调用1.6锁的升级过程_第5张图片

1.6锁的升级过程_第6张图片

调用完对象的HashCode方法后,这个对象将永远无法转成偏向锁。只能转成轻量级锁或者重量级锁,为了不能转成偏向锁,是因为HashCode生成了以后,在升级成偏向锁,没有地方存这个hashCode,因为官方的建议是hashCode只能生成一次。

或者说当线程获得偏向锁时,我们调用HashCode方法,锁会升级成了轻量级锁或者重量级锁。

在这里插入图片描述
轻量级锁时,栈的锁指针记录可以保存hashCode.

在这里插入图片描述

你可能感兴趣的:(java,开发语言)