Java Synchronized 偏向锁/轻量级锁/重量级锁的演变过程
2023-09-29 17:17:28
Java Synchronized 偏向锁/轻量级锁/重量级锁的演变过程
前言
上篇文章已经分析了Java对象头构成、源码及其对象头的调试,本篇将分析偏向锁、轻量级锁、重量级锁的实现及其演变过程。由于涉及到c++源码,估计不少同学没兴趣看,因此重点多以图+源码辅助分析。
偏向锁
偏向锁是一种轻量级的锁,当一个线程获取对象锁时,会将对象头中的锁标志位设置为偏向锁状态,并将其指向该线程。这样,当其他线程尝试获取该对象锁时,会先检查对象的锁标志位,如果发现是偏向锁状态,则直接返回,不会阻塞。
偏向锁的优点在于开销小,因为不需要像重量级锁那样每次获取锁都必须进入内核态。但偏向锁也有一个缺点,就是它只能在没有竞争的情况下使用。如果有多个线程同时尝试获取同一个对象锁,则偏向锁就会失效,退化为重量级锁。
轻量级锁
轻量级锁是一种比偏向锁更轻量级的锁,它使用一个CAS操作来尝试获取对象锁。如果CAS操作成功,则表示该线程获得了对象锁,否则表示该线程获取对象锁失败,需要阻塞等待。
轻量级锁的优点在于它比重量级锁开销更小,并且可以避免偏向锁在多线程竞争的情况下失效。但轻量级锁也有一个缺点,就是它可能会导致ABA问题。
重量级锁
重量级锁是最传统的锁,它使用一个互斥量来获取对象锁。当一个线程获取对象锁时,会将互斥量设置为加锁状态,其他线程尝试获取该对象锁时,会阻塞等待,直到互斥量被释放。
重量级锁的优点在于它可以解决ABA问题,并且可以保证对象的锁在任何情况下都是有效的。但重量级锁的开销也最大,因为它需要每次获取锁都必须进入内核态。
偏向锁、轻量级锁、重量级锁的演变过程
偏向锁、轻量级锁和重量级锁的演变过程如下图所示:
+----------------------+
| |
| 偏向锁 |
| |
+----------------------+
|
V
+------------------------+
| |
| 轻量级锁 |
| |
+------------------------+
|
V
+--------------------------+
| |
| 重量级锁 |
| |
+--------------------------+
从图中可以看出,偏向锁是最轻量级的锁,其次是轻量级锁,最后是重量级锁。随着锁的重量级增加,锁的开销也越来越大,但锁的安全性也越来越高。
总结
偏向锁、轻量级锁和重量级锁是 Java 中的三种锁类型,它们各有其特点和适用场景。在实际应用中,需要根据具体情况选择合适的锁类型。