偏向锁

简介: 基础

根据上面的表来看,Mark Word后三位为101时,加锁对象的状态为偏向锁,偏向锁的意义在于同一个线程访问sychronize代码块时不需要进行加锁,解锁操作,性能开销更低(HotSpot[1]的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。)

因为正常情况下,当一个线程访问同步块并获取轻量级锁时,需要进行CAS操作将对象头的锁记录里指向当前线程的栈中的锁记录,执行完毕后需要释放轻量级锁。如果是同一个线程多次访问sychronize代码块,多次获取和释放轻量级,开销会偏大,所以会一开始判断对象是无锁状态,会将对象头设置为偏向锁,并且这个的线程ID添加到锁对象的Mark Word中,后续同一线程判断加锁标志是偏向锁,并且线程ID一致就可以直接执行。偏向锁的加锁过程:

场景一:当锁对象第一次被线程获得锁的时候

线程发现是匿名偏向状态(也就是锁对象的Mark Word没有存储线程ID),则会用CAS指令,将 mark word中的thread id由0改成当前线程Id。如果成功,则代表获得了偏向锁,继续执行同步块中的代码。否则,将偏向锁撤销,升级为轻量级锁。

场景二:当获取偏向锁的线程再次进入同步块时

发现锁对象存储的线程ID就是当前线程的ID,会往当前线程的栈中添加一条 DisplacedMarkWord为空的 LockRecord中,然后继续执行同步块的代码,因为操纵的是线程私有的栈,因此不需要用到CAS指令;由此可见偏向锁模式下,当被偏向的线程再次尝试获得锁时,仅仅进行几个简单的操作就可以了,在这种情况下, synchronized关键字带来的性能开销基本可以忽略。

场景二:当没有获得锁的线程进入同步块时

当没有获得锁的线程进入同步块时,发现当前是偏向锁状态,并且存储的是其他线程ID(也就是其他线程正在持有偏向锁),则会进入到撤销偏向锁的逻辑里,一般来说,会在 safepoint中去查看偏向的线程是否还存活

  • 如果线程存活且还在同步块中执行, 则将锁升级为轻量级锁,原偏向的线程继续拥有锁,只不过持有的是轻量级锁,继续执行代码块,执行完之后按照轻量级锁的解锁方式进行解锁,而其他线程则进行自旋,尝试获得轻量级锁。
  • 如果偏向的线程已经不存活或者不在同步块中, 则将对象头的 mark word改为无锁状态(unlocked)

由此可见,偏向锁升级的时机为:当一个线程获得了偏向锁,在执行时,只要有另一个线程尝试获得偏向锁,并且当前持有偏向锁的线程还在同步块中执行,则该偏向锁就会升级成轻量级锁。


相关文章
|
8月前
|
Java
java中的锁是一种同步机制,用于控制并发访问共享资源的线程。在多线程程序中,如果多个线程同时访问同一个共享资源,就可能会导致数据不一致或者死锁等问题。Java中提供了多种锁机制来解决这些问题,常见的包括synchronized关键字、ReentrantLock类、Read/Write Lock等。
38 0
|
1月前
|
存储 安全 Java
12.synchronized的锁重入、锁消除、锁升级原理?无锁、偏向锁、轻量级锁、自旋、重量级锁
12.synchronized的锁重入、锁消除、锁升级原理?无锁、偏向锁、轻量级锁、自旋、重量级锁
43 0
12.synchronized的锁重入、锁消除、锁升级原理?无锁、偏向锁、轻量级锁、自旋、重量级锁
|
9月前
|
存储 算法 安全
辛辛苦苦的劳动成果,如何上把锁?
辛辛苦苦的劳动成果,如何上把锁?
|
11月前
《锁》有那些?
锁是计算机科学中用于控制对共享资源的访问的一种同步机制。不同种类的锁适用于不同的场景和需求。下面是一些常见的锁的种类及其详细介绍:
55 1
|
11月前
|
存储 Java
重量级锁,偏向锁和轻量级锁
重量级锁,偏向锁和轻量级锁
82 0
|
Java
各种锁的理解
各种锁的理解
99 0
各种锁的理解
|
生物认证
什么是锁?
什么是锁?
97 0
什么是锁?
|
存储 Java
identityHashCode与偏向锁
我们知道在Java中,一切对象都继承自java.lang.Object类。这个类中有一个可继承的方法叫hashCode()。
281 0
Juc20_Synchronized锁升级、无锁、偏向锁、轻量级锁、重量级锁、锁消除、锁粗化(四)
⑤. 重锁 会有用户态、内核态切换 ⑥. 各种锁优缺点、synchronized锁升级和实现原理
142 0
Juc20_Synchronized锁升级、无锁、偏向锁、轻量级锁、重量级锁、锁消除、锁粗化(四)