当前位置:首页 > Java

java锁是如何实现的

2026-03-03 15:21:10Java

Java锁的实现机制

Java中的锁机制主要通过synchronized关键字和java.util.concurrent.locks包下的显式锁(如ReentrantLock)实现。以下是两种锁的核心实现原理:

synchronized的实现

synchronized基于JVM内置的监视器锁(Monitor)实现,依赖对象头中的Mark Word和线程栈帧中的锁记录(Lock Record)。

对象头结构
32位JVM的Mark Word布局(以偏向锁为例):

|-------------------------------------------------------|--------------------|
|                  Mark Word (32 bits)                   |       State        |
|-------------------------------------------------------|--------------------|
| hashcode:25 | age:4 | biased_lock:1 | lock:2 (01)      |       Normal       |
| thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 (01)|      Biased       |
| ptr_to_lock_record:30                         | lock:2 (00)| Lightweight Locked |
| ptr_to_heavyweight_monitor:30                 | lock:2 (10)| Heavyweight Locked |
|                                              | lock:2 (11)|    Marked for GC   |
|-------------------------------------------------------|--------------------|

锁升级过程

  1. 无锁状态:初始状态,对象未被任何线程锁定。
  2. 偏向锁:通过CAS设置Mark Word中的线程ID,适用于单线程重复访问场景。
  3. 轻量级锁:当多线程竞争时,撤销偏向锁,线程通过CAS将Mark Word替换为指向栈中锁记录的指针。
  4. 重量级锁:竞争加剧时,轻量级锁升级为重量级锁,未获取锁的线程进入阻塞状态,依赖操作系统的互斥量(Mutex)。

ReentrantLock的实现

ReentrantLock基于AQS(AbstractQueuedSynchronizer)实现,核心通过CAS操作和CLH队列管理线程阻塞与唤醒。

AQS核心结构

  • state字段:表示锁的重入次数(如0表示未锁定,≥1表示被持有)。
  • CLH队列:双向链表结构的等待队列,节点保存阻塞线程信息。

加锁流程(非公平锁为例)

final void lock() {
    if (compareAndSetState(0, 1)) // CAS尝试直接获取锁
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1); // 进入AQS排队逻辑
}

AQS的acquire方法

java锁是如何实现的

  1. 尝试通过tryAcquire获取锁(子类实现,如检查state是否为0)。
  2. 失败后将线程封装为Node加入队列尾部,通过LockSupport.park阻塞线程。
  3. 前驱节点释放锁时,唤醒后续节点重新竞争。

锁的对比

特性 synchronized ReentrantLock
实现层级 JVM内置 JDK代码层面
公平性 非公平 支持公平/非公平(构造函数指定)
中断响应 不支持 支持lockInterruptibly
条件变量 单一wait/notify 支持多个Condition
锁释放 自动(代码块结束) 需手动unlock

性能优化建议

  • 偏向锁:适用于单线程占优场景,可通过JVM参数-XX:+UseBiasedLocking启用(JDK 15后默认禁用)。
  • 自旋优化:重量级锁竞争时,线程会自旋尝试获取锁(通过-XX:PreBlockSpin调整自旋次数)。
  • 锁消除:JIT编译器对不可能存在竞争的锁进行消除(如局部对象锁)。
  • 锁粗化:将相邻的同步块合并减少锁开销。

通过合理选择锁类型和优化参数,可以平衡线程安全与性能需求。

分享给朋友:

相关文章

vue如何实现

vue如何实现

Vue 实现方法 在 Vue 中实现功能通常涉及组件化开发、状态管理和响应式数据绑定。以下是几种常见的实现方式: 组件化开发 使用 Vue 的单文件组件(.vue 文件)结构,将 UI 拆分为可复用…

如何用java

如何用java

用Java实现基础功能 Java是一种广泛使用的编程语言,适用于开发各种应用程序。以下是几个常见功能的实现方法。 打印"Hello, World!" public class HelloWorld…

如何配置java

如何配置java

安装Java开发工具包(JDK) 访问Oracle官方网站或OpenJDK项目页面下载适合操作系统的JDK安装包。选择与系统架构匹配的版本(如Windows x64、macOS ARM等)。运行安装程…

如何学习java

如何学习java

学习Java的步骤 理解基础知识 从Java的基本语法开始,包括变量、数据类型、运算符、控制流(if-else、循环)等。掌握这些基础概念是后续学习的基石。 学习面向对象编程(OOP) Java是一…

vue如何实现拖动

vue如何实现拖动

Vue 实现拖动的常用方法 使用 HTML5 原生拖放 API HTML5 提供了原生的拖放 API,可以通过 draggable 属性和相关事件实现拖动功能。 <template>…

如何卸载java

如何卸载java

卸载Java的步骤 Windows系统卸载方法 打开控制面板,选择“程序和功能”或“卸载程序”。在列表中找到Java相关条目(如“Java 8 Update 251”),右键选择卸载并跟随向导完成操…