高并发下ReentrantLock和synchronized性能对比分析

1个回答

写回答

duanyinmo

2026-02-05 02:25

+ 关注

结论是,在不同版本的 JDK 中,某些场景下确实不建议使用 synchronized。下面我来详细说明一下相关的背景。 背景分析在早期的 JDK 版本中,synchronized 默认会对临界资源添加重量级锁,即使可能存在完全没有竞争的情况,只要进入临界区,就会无条件地加锁。这种机制虽然简单直接,但在性能上存在明显的瓶颈,尤其是在高并发场景下。接下来我们从不同的 JDK 版本出发,逐步探讨在不同场景下的选择策略。

不同版本的推荐 1. 如果使用的是 JDK 1.5 或更早版本很遗憾,在这些版本中你没有其他选择,只能先将就着使用 synchronized 的重量级锁机制。这是因为当时的实现尚未引入轻量级锁、偏向锁等优化,所有同步操作都默认使用重量级锁,性能损耗较大。 2. 如果使用的是 JDK 1.5在这种情况下,推荐使用 ReentrantLock。因为此时的 synchronized 仍然是默认加重量级锁,而 ReentrantLock 提供了更灵活的锁控制机制,例如支持公平锁和非公平锁、可中断等待等功能。如果对锁的灵活性要求较高,ReentrantLock 是更好的选择。 3. JDK 1.6 的改进从 JDK 1.6 开始,官方对 synchronized 进行了一系列优化,主要包括以下几点:1. 锁消除 JVM 在运行时会进行逃逸分析,判断对象是否会被多个线程访问。如果确定某个同步块中的对象不会被多个线程共享,则可以省略掉同步操作,从而避免不必要的性能开销。2. 锁粗化 如果一系列连续的同步操作作用于同一个对象,JVM 会将这些操作合并为一个更大的同步块,减少频繁加锁和解锁带来的开销。3. 锁升级 这是最重要的改进之一,synchronized 的锁状态会经历以下四个阶段: - 无锁:初始状态,没有任何锁。 - 偏向锁:当只有一个线程访问同步块时,JVM 会将该锁偏向这个线程,避免不必要的加锁操作。 - 轻量级锁:当有多个线程竞争但竞争程度较低时,JVM 使用自旋锁机制,避免线程阻塞。 - 重量级锁:只有当竞争激烈且自旋锁失败时,才会升级为重量级锁。

锁升级的核心特性 自旋锁的作用自旋锁是轻量级锁的核心机制之一。了解 JVM 并发编程模型的人都知道,在 JDK 21 LTS 推出虚拟线程之前,线程的调度完全依赖于底层操作系统内核。这意味着线程的创建、等待、唤醒和销毁等操作都需要调用操作系统的内核 API,这是一个非常耗时且耗费资源的过程。在引入锁升级特性后,synchronized 的性能得到了显著提升。特别是在竞争较弱的情况下,通过自旋锁可以避免线程进入阻塞状态,从而大幅提升性能。自旋锁的优点在于它能够在短时间内快速尝试获取锁,而无需切换到内核态。

JDK 1.6 及其后续版本的表现从 JDK 1.6 开始,synchronized 的性能已经不再逊色于 ReentrantLock。由于锁升级特性的引入,synchronized 在许多场景下甚至表现得更为优秀。具体来说:- 当竞争较弱时,synchronized 可以利用偏向锁和轻量级锁,避免线程阻塞。- 当竞争较强时,虽然会升级为重量级锁,但仍然可以通过 JVM 的优化机制尽量减少性能损失。因此,在 JDK 1.6 及后续版本中,synchronized 已经成为一种高效且易用的同步工具。

高并发场景下的对比当 JDK 版本满足 JDK 1.6

举报有用(0分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号