详解synchronized锁升级机制:从偏向锁到重量级锁
2023-05-19 08:06:36
并发编程中的锁升级:从偏向锁到重量级锁
在 Java 并发编程中,synchronized 锁是一种广泛使用的同步机制,它通过对象头加锁来确保共享数据的并发访问。synchronized 锁具备锁升级的特性,当锁定的对象同时被多个线程访问时,锁会从偏向锁升级为轻量级锁,若竞争激烈,还会进一步升级为重量级锁。
偏向锁:轻量级保护
偏向锁是一种轻量级的锁,它通过在对象头中存储一个线程 ID 来实现。当一个线程首次获取偏向锁时,它会将自己的线程 ID 存储在对象头中。后续当该线程再次获取该对象的锁时,它只需检查对象头中的线程 ID 是否与自己的线程 ID 一致,若一致则可直接获取锁。否则,线程需要升级为轻量级锁。
轻量级锁:高效并发
轻量级锁也是一种轻量级的锁,它通过在对象头中存储一个锁标志位和一个等待队列来实现。当一个线程首次获取轻量级锁时,它会将锁标志位设置为 1,并将自己加入等待队列中。后续当该线程再次获取该对象的锁时,它只需检查锁标志位是否为 1,若为 1 则可直接获取锁。否则,线程需要升级为重量级锁。
重量级锁:稳重保障
重量级锁是最传统的锁,它通过在对象头中存储一个监视器对象来实现。当一个线程首次获取重量级锁时,它会获取监视器对象的锁。后续当该线程再次获取该对象的锁时,它只需检查监视器对象是否被其他线程持有,若被持有则需要等待其他线程释放锁。
锁升级的原理:高效竞争
synchronized 锁的升级原理很简单,当一个对象的锁同时被多个线程访问时,锁会从偏向锁升级为轻量级锁,若竞争激烈,还会进一步升级为重量级锁。锁升级的目的是为了提高并发性能。偏向锁和轻量级锁都是轻量级的锁,它们可以减少锁竞争的开销。当锁竞争激烈时,升级为重量级锁可以减少线程等待锁的开销。
锁升级的示例:代码实战
public class SynchronizedLockUpgrade {
private final Object lock = new Object();
public void synchronizedMethod() {
synchronized (lock) {
// do something
}
}
public static void main(String[] args) {
SynchronizedLockUpgrade object = new SynchronizedLockUpgrade();
Thread thread1 = new Thread(() -> {
object.synchronizedMethod();
});
Thread thread2 = new Thread(() -> {
object.synchronizedMethod();
});
thread1.start();
thread2.start();
}
}
在该示例中,两个线程同时调用 synchronizedMethod() 方法。由于 lock 对象首次被访问,因此它处于偏向锁状态。当第一个线程获取 lock 对象的锁后,它会将自己的线程 ID 存储在 lock 对象的头中。当第二个线程获取 lock 对象的锁时,它会检查 lock 对象的头中的线程 ID 是否与自己的线程 ID 一致。由于不一致,因此第二个线程需要升级为轻量级锁。当第二个线程获取 lock 对象的锁后,它会将自己的线程 ID 存储在 lock 对象的头中。后续,当这两个线程再次获取 lock 对象的锁时,它们都可以直接获取锁。
总结:并发性能优化
synchronized 锁的升级机制是一种非常重要的并发机制,它可以显著提高并发性能。偏向锁和轻量级锁都是轻量级的锁,它们可以减少锁竞争的开销。当锁竞争激烈时,升级为重量级锁可以减少线程等待锁的开销。理解 synchronized 锁的升级机制可以帮助开发者编写出更高效的并发程序。
常见问题解答
-
什么是锁升级?
锁升级是一种机制,当锁定的对象同时被多个线程访问时,锁会从偏向锁升级为轻量级锁,若竞争激烈,还会进一步升级为重量级锁。 -
为什么需要锁升级?
锁升级可以提高并发性能。偏向锁和轻量级锁都是轻量级的锁,它们可以减少锁竞争的开销。当锁竞争激烈时,升级为重量级锁可以减少线程等待锁的开销。 -
偏向锁和轻量级锁有什么区别?
偏向锁通过在对象头中存储一个线程 ID 来实现,而轻量级锁通过在对象头中存储一个锁标志位和一个等待队列来实现。偏向锁的开销更低,但仅适用于无竞争场景,而轻量级锁开销略高,但可以处理竞争场景。 -
如何判断锁的类型?
可以通过Object.getClass().getName()
方法判断锁的类型。偏向锁的类名为 java.util.concurrent.locks.BiasedLock ,轻量级锁的类名为 java.util.concurrent.locks.轻量级Lock ,重量级锁的类名为 java.util.concurrent.locks.重量级Lock 。 -
如何优化锁升级?
可以通过以下方式优化锁升级:- 减少锁竞争:通过适当的数据结构和算法来减少锁竞争。
- 使用自旋锁:自旋锁是一种轻量级的锁,它可以减少线程等待锁的开销。
- 使用读写锁:读写锁允许多个线程同时读取共享数据,从而减少锁竞争。