问答题1014/1053说一下synchronized锁升级过程

难度:
2021-11-02 创建

参考答案:

synchronized 锁的升级过程是 Java 虚拟机(JVM)为了提高多线程并发性能而引入的一种优化策略。这个过程通过减少锁竞争的代价,提升了锁的效率。Java 中的 synchronized 锁从轻量级锁到重量级锁有一个逐步升级的过程,下面是锁的升级过程详细描述:

1. 无锁状态(No Lock)

当多个线程访问共享资源时,如果没有其他线程竞争该资源,JVM 会认为该资源不需要加锁。此时,线程可以安全地访问共享变量,而不需要进行加锁操作。

2. 偏向锁(Biased Locking)

偏向锁是 Java 6 引入的一种优化机制,旨在避免无竞争的情况下使用锁。具体来说,如果一个线程访问某个对象并获得了该对象的锁,那么 JVM 会将该对象的锁标记为“偏向”该线程,即使之后该线程多次访问这个对象,也不需要再进行加锁操作,锁会一直偏向这个线程。

  • 偏向锁适用于线程访问的对象没有竞争的情况。
  • 如果对象的偏向锁已经获得,当另一个线程尝试获取该对象锁时,偏向锁会被撤销,锁升级为轻量级锁。

偏向锁的优势是大大减少了无竞争情况下的锁操作,提升了性能。

3. 轻量级锁(Lightweight Locking)

当多个线程竞争同一个对象的锁时,JVM 会使用轻量级锁。轻量级锁的实现依赖于 CAS(Compare and Swap)操作,它会使用一个称为 lock 的标志位来尝试获取锁。

  • 如果某个线程发现该对象的锁为空(即没有其他线程持有锁),它会通过 CAS 操作来设置锁,并进入临界区。
  • 如果有其他线程竞争该锁,轻量级锁就会失败,锁会升级为重量级锁。

轻量级锁的优点是,当没有线程竞争时,它几乎不产生任何性能开销,并且其性能优于偏向锁。

4. 重量级锁(Heavyweight Locking)

当轻量级锁失败,或多个线程竞争同一个锁时,JVM 会将锁升级为重量级锁(即操作系统层面的互斥锁)。在重量级锁下,线程需要通过操作系统的线程调度来获取锁,这会引起线程的上下文切换和较高的开销。

  • 当锁是重量级锁时,只有一个线程能够持有该锁,其他线程必须等待,直到持有锁的线程释放锁。

重量级锁的开销较大,因此它通常在高竞争场景下发生,当多线程竞争资源频繁时,锁会被提升为重量级锁。

锁升级过程总结:

  • 无锁状态:没有竞争时,不需要加锁。
  • 偏向锁:如果一个线程独占资源,锁会偏向该线程,避免其他线程获取锁。
  • 轻量级锁:当多个线程竞争锁时,使用 CAS 实现轻量级锁。
  • 重量级锁:如果轻量级锁失败或竞争激烈,锁升级为重量级锁,导致较高的性能开销。

锁升级的触发条件:

  • 偏向锁:当锁没有竞争时,锁偏向当前线程。如果有其他线程竞争,偏向锁会被撤销。
  • 轻量级锁:当多个线程竞争同一资源时,偏向锁会升级为轻量级锁。
  • 重量级锁:如果轻量级锁的 CAS 操作失败,或者锁竞争非常激烈,锁会升级为重量级锁。

锁降级:

  • 锁降级通常发生在持有锁的线程释放锁时。虽然 JDK 中没有提供明确的锁降级机制,但可以通过一些设计(例如通过 synchronized 方法和块在不同的作用域内使用)间接实现“降级”效果。例如,在使用可重入锁(ReentrantLock)时,线程可以在同一锁上进行加锁和释放锁的操作,避免了过度的锁竞争。

最近更新时间:2024-12-06