Java 中锁升级的流程是什么?

· 约 2 分钟读完 · 第 96 / 274 章

推荐答案

在Java中,锁升级是指从无锁状态逐步升级到偏向锁、轻量级锁,最后到重量级锁的过程。锁升级的目的是为了在多线程环境下减少锁的开销,提高性能。锁升级的流程如下:

  1. 无锁状态:当一个对象刚被创建时,它处于无锁状态。
  2. 偏向锁:当第一个线程访问该对象时,JVM会将对象头中的标记设置为偏向锁,并记录下线程ID。此时,如果同一个线程再次访问该对象,JVM会直接允许访问,无需加锁。
  3. 轻量级锁:当有多个线程竞争同一个对象时,偏向锁会升级为轻量级锁。JVM会在当前线程的栈帧中创建一个锁记录(Lock Record),并将对象头中的标记替换为指向该锁记录的指针。此时,线程会通过CAS操作尝试获取锁。
  4. 重量级锁:如果轻量级锁的竞争激烈,JVM会将轻量级锁升级为重量级锁。重量级锁会使用操作系统的互斥量(Mutex)来实现,此时线程会进入阻塞状态,等待锁的释放。

本题详细解读

1. 无锁状态

当一个对象刚被创建时,它处于无锁状态。此时,对象头中的标记位(Mark Word)没有任何锁信息。

2. 偏向锁

偏向锁是为了在单线程环境下减少锁的开销。当一个线程第一次访问该对象时,JVM会将对象头中的标记设置为偏向锁,并记录下线程ID。此时,如果同一个线程再次访问该对象,JVM会直接允许访问,无需加锁。

  • 优点:在单线程环境下,偏向锁可以避免不必要的加锁操作,提高性能。
  • 缺点:如果有多线程竞争,偏向锁会失效,需要升级为轻量级锁。

3. 轻量级锁

当有多个线程竞争同一个对象时,偏向锁会升级为轻量级锁。JVM会在当前线程的栈帧中创建一个锁记录(Lock Record),并将对象头中的标记替换为指向该锁记录的指针。此时,线程会通过CAS操作尝试获取锁。

  • 优点:轻量级锁通过CAS操作避免了线程阻塞,减少了上下文切换的开销。
  • 缺点:如果CAS操作失败,说明有竞争,轻量级锁会升级为重量级锁。

4. 重量级锁

如果轻量级锁的竞争激烈,JVM会将轻量级锁升级为重量级锁。重量级锁会使用操作系统的互斥量(Mutex)来实现,此时线程会进入阻塞状态,等待锁的释放。

  • 优点:重量级锁可以保证线程安全,适用于高并发场景。
  • 缺点:重量级锁会导致线程阻塞,增加了上下文切换的开销,性能较低。

总结

锁升级的过程是从无锁状态逐步升级到偏向锁、轻量级锁,最后到重量级锁。锁升级的目的是为了在多线程环境下减少锁的开销,提高性能。不同的锁状态适用于不同的并发场景,开发者需要根据实际情况选择合适的锁机制。