返回
剖析 Synchronized 锁升级:从偏向到重量级
后端
2023-10-24 18:01:44
在 Java 并发编程中,synchronized
是一个重量级的锁,但它并非生来如此。它有一个进化过程,从轻巧的偏向锁到沉重的重量级锁,这被称为锁升级。本文将深入探讨 synchronized 锁升级的底层原理。
锁升级的起源
synchronized 锁升级的本质是通过逐渐提升锁的开销来提高并发性能。当竞争不激烈时,偏向锁和轻量级锁开销低,可以提高性能。当竞争加剧时,重量级锁介入,以确保线程安全。
偏向锁
偏向锁是最轻量的锁,它假设线程对对象的访问具有局部性,即一个线程在一段时间内会一直访问同一个对象。偏向锁会记录当前线程的 ID,如果其他线程试图访问该对象,偏向锁会立即检查线程 ID 是否匹配。如果匹配,则直接让该线程获取锁;如果不匹配,则偏向锁会升级为轻量级锁。
轻量级锁
轻量级锁比偏向锁开销稍大,它通过使用一个名为 "锁记录" 的数据结构来实现。锁记录包含线程 ID、对象指针和其他元数据。当线程试图获取轻量级锁时,它会尝试将锁记录中的线程 ID 修改为自己的 ID。如果修改成功,则线程获取锁;如果修改失败,则轻量级锁会升级为重量级锁。
重量级锁
重量级锁是开销最大的锁,它通过使用一个监视器对象来实现。监视器对象包含一个队列,用于存储等待获取锁的线程。当线程试图获取重量级锁时,它会进入队列并等待。当锁释放时,队列中的第一个线程会获取锁。
锁升级的过程
锁升级的具体过程如下:
- 偏向锁: 假设一个线程对对象具有局部性,偏向锁会记录该线程的 ID。
- 轻量级锁: 如果其他线程试图访问该对象,偏向锁会升级为轻量级锁。轻量级锁通过修改锁记录中的线程 ID 来获取锁。
- 重量级锁: 如果多个线程同时竞争获取轻量级锁,轻量级锁会升级为重量级锁。重量级锁通过使用监视器对象和队列来管理等待获取锁的线程。
何时发生锁升级
锁升级通常发生在以下情况下:
- 竞争激烈: 当多个线程同时争用同一对象时,轻量级锁会升级为重量级锁以确保线程安全。
- 对象的哈希冲突: 如果多个对象具有相同的哈希码,轻量级锁会升级为重量级锁以防止哈希冲突。
- 调用
wait()
或notify()
: 当一个线程调用wait()
或notify()
方法时,轻量级锁会升级为重量级锁以确保线程安全。
锁升级的好处
锁升级提供了以下好处:
- 提高性能: 在竞争不激烈的情况下,偏向锁和轻量级锁的开销较低,可以提高性能。
- 确保线程安全: 重量级锁可以确保线程安全,即使在竞争激烈的环境中也是如此。
结论
Synchronized 锁升级是一种重要的并发机制,它可以根据竞争情况动态调整锁的开销。通过理解锁升级的原理,开发者可以更好地利用 synchronized 锁来实现高效且线程安全的并发程序。