关于Synchronized和ReentrantLock
锁优化机制
| 术语 | 定义 |
|---|---|
| 偏向锁(Biased Locking) | JVM 锁优化策略。当同步块持续被同一线程获取时,锁对象头中的 Mark Word 会记录该线程 ID,后续该线程进入同步块无需 CAS 操作,仅比较线程 ID 即可。适用于无竞争场景,消除无竞争同步的原子操作开销。JDK 15 起默认禁用。 |
| 轻量级锁(Lightweight Locking) | 当偏向锁遇到竞争时,JVM 将对象头替换为指向线程栈中 Lock Record 的指针,通过 CAS 自旋获取锁。避免线程阻塞和内核态切换,适用于线程交替执行、竞争短暂的场景。 |
| 自适应自旋(Adaptive Spinning) | 动态调整自旋等待时间的策略。JVM 根据前一次自旋获取锁的成功率及持有时间,智能预测本次自旋次数,成功率高则增加自旋,反之直接挂起线程,平衡 CPU 消耗与响应延迟。 |
锁类型
| 术语 | 定义 |
|---|---|
| synchronized | Java 语言层面的内置同步机制,基于 Monitor(监视器)实现。通过 monitorenter / monitorexit 字节码指令操作对象头的 Mark Word,依赖 JVM 进行锁升级和优化。 |
| ReentrantLock | java.util.concurrent.locks 包提供的显式可重入互斥锁,基于 AQS(AbstractQueuedSynchronizer)框架实现。需手动调用 lock() / unlock(),支持公平锁、可中断、超时获取、条件变量等扩展语义。 |
JVM 编译与运行时优化
| 术语 | 定义 |
|---|---|
| 锁消除(Lock Elision) | 逃逸分析(Escape Analysis)的应用。JIT 编译器判定某同步块的对象引用不会逃逸出当前线程(即无共享访问),则直接移除同步代码,消除锁开销。 |
| 锁粗化(Lock Coarsening) | JIT 编译器将相邻的多个连续同步块(通常由循环展开或频繁加锁解锁导致)合并为范围更大的单一同步区域,减少重复的加锁解锁操作次数,降低同步开销。 |
| JIT 编译(Just-In-Time Compilation) | JVM 将热点字节码动态编译为本地机器码的执行方式。通过方法调用计数器与回边计数器触发编译,使高频代码以接近原生性能运行,并为深度优化(如内联、逃逸分析)提供基础。 |
| 内存布局(Memory Layout) | 对象在堆内存中的结构化存储方式。synchronized 的锁状态直接编码在对象头(Object Header)的 Mark Word 中,而 ReentrantLock 作为独立对象实例,需额外的对象头开销和指针解引用,缓存局部性更差。 |
并发基础概念
| 术语 | 定义 |
|---|---|
| 对象头(Object Header) | HotSpot 虚拟机中对象在堆中的元数据区域,包含 Mark Word(存储哈希码、GC 年龄、锁状态标志等)和类型指针(Klass Pointer)。锁升级过程中,Mark Word 的 64 位/32 位数据会动态重用以存储锁状态信息。 |
| Mark Word | 对象头的第一部分,用于存储对象自身的运行时数据。在不同锁状态下,其位布局动态变化:无锁时存哈希码和分代年龄;偏向锁时存线程 ID;轻量级锁时存指向 Lock Record 的指针;重量级锁时存指向 Monitor 的指针。 |
| Monitor(监视器) | 操作系统层面的同步机制实现,对应 ObjectMonitor 结构。包含 _owner(持有线程)、_EntryList(阻塞队列)、_WaitSet(等待队列)等字段。依赖操作系统互斥量(mutex)和条件变量(condition variable),涉及用户态与内核态切换,开销最大。 |
| CAS(Compare-And-Swap) | 原子操作指令,通过比较内存值与预期值,若相等则更新为新值。轻量级锁和 AQS 框架的核心原语,属于无锁算法(Lock-Free)的基础,但存在 ABA 问题和自旋开销。 |
| AQS(AbstractQueuedSynchronizer) | java.util.concurrent 包的核心抽象框架,提供基于 FIFO 等待队列的阻塞式锁和同步器基础。ReentrantLock、Semaphore、CountDownLatch 等均基于 AQS 实现,通过 CAS 管理 state 状态和双向链表队列。 |
线程状态与调度
| 术语 | 定义 |
|---|---|
| 内核态切换(Context Switch) | 线程从用户态进入内核态(或反之)的 CPU 特权级转换。重量级锁竞争失败时,线程调用 pthread_mutex_lock 进入内核阻塞,触发上下文切换,保存/恢复寄存器状态,代价高昂(通常微秒级)。 |
| 用户态自旋(User-Level Spinning) | 线程在用户空间通过循环空转(while + pause 指令)等待锁释放,不释放 CPU 时间片也不陷入内核。利用多核 CPU 的缓存一致性协议监听锁状态变化,避免上下文切换,但持续占用 CPU 周期。 |
权威参考
| 术语 | 定义 |
|---|---|
| Doug Lea | Java 并发编程领域核心人物,纽约州立大学奥斯威戈分校计算机科学教授。主导设计 java.util.concurrent(JSR 166)包,包括 AQS 框架、原子类、并发集合等,其著作《Concurrent Programming in Java》为并发经典教材。 |

浙公网安备 33010602011771号