Synchronized 的轻量锁

2020-05-14 17:07:39 +08:00
 xiaobaobao
在 synchronized 的锁升级到轻量级锁后,其他线程进行 CAS 竞争锁,可是如果此时持有锁的线程正在执行中,jvm 是如何保证此时是获取锁失败的?看了很多文章,都没提这一点,就是简单的判断下原持有锁线程状态吗?
1655 次点击
所在节点    Java
4 条回复
guyeu
2020-05-14 17:39:05 +08:00
你可以理解为每个对象都有一个属性,用来标记它是不是被持有锁,如果线程请求的一个锁被持有,就无法获取这个锁。
1ffree
2020-05-14 18:40:04 +08:00
对象头 状态位
Aresxue
2020-05-15 11:52:40 +08:00
轻量锁的竞争是 JVM 利用 CAS 操作,尝试将对象的 Mark Word 更新为指向 Lock Record 的指针, 如果这时候其他线程已经持有锁, 那么这里就会失败
fantastM
2020-05-15 14:14:38 +08:00
有篇 OpenJDK 文章可以先看一下 https://wiki.openjdk.java.net/display/HotSpot/Synchronization

相关的 JVM 实现代码可以看这里 http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp

按照 OpenJDK 的说法,JVM 是这样实现的(先不考虑偏向锁):

`In the Java HotSpot™ VM, every object is preceded by a class pointer and a header word. The header word, which stores the identity hash code as well as age and marking bits for generational garbage collection, is also used to implement a thin lock scheme.` Java 中的每个对象都有关联的 class pointer 和 header word,Java 是用 header word 来实现 thin lock 的。

`As long as an object is unlocked, the last two bits have the value 01. ` 当对象没有被锁定的时候,header word 最后两位是 01 。

`When a method synchronizes on an object, the header word and a pointer to the object are stored in a lock record within the current stack frame. Then the VM attempts to install a pointer to the lock record in the object's header word via a compare-and-swap operation.` 当对象被 synchronized 的时候,这个对象的 header word 和 class pointer 会先被存储到当前线程 stack frame 中(类似于先保存一下数据的副本),这条栈帧被叫 lock record 。然后 JVM 尝试通过 CAS 操作,把 lock record 的指针记录在对象原先的 header word (前几位)中。

`If it succeeds, the current thread afterwards owns the lock. Since lock records are always aligned at word boundaries, the last two bits of the header word are then 00 and identify the object as being locked.` 如果这个 CAS 操作成功,就表示当前线程获取到了锁,对象的 header word 的最后两位会被设置成 00 。

`If the compare-and-swap operation fails because the object was locked before, the VM first tests whether the header word points into the method stack of the current thread.` 如果这个 CAS 操作失败,JVM 会先检查一下对象的 header word (前几位)里的 lock record 指针是否指向了当先线程的方法栈。(如果是的话,这个对象应该是 recursively locked object,这也就是 synchronized 的可重入特性;如果不是的话,就表示有多个线程在竞争这个对象的锁。)

`Only if two different threads concurrently synchronize on the same object, the thin lock must be inflated to a heavyweight monitor for the management of waiting threads.` 如果有两个不同的线程在竞争同一个对象的锁,thin lock 升级成 heavyweight monitor 。

Java 对象中 header word 的 bit format,可以看第二个链接的 37-54 行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/671698

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX