当前位置:首页 > 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方法

  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编译器对不可能存在竞争的锁进行消除(如局部对象锁)。
  • 锁粗化:将相邻的同步块合并减少锁开销。

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

java锁是如何实现的

分享给朋友:

相关文章

vue自动登录如何实现

vue自动登录如何实现

实现自动登录的基本思路 自动登录通常通过结合本地存储(如localStorage或cookie)和token验证机制实现。用户首次登录成功后,服务器返回的认证token会被保存在客户端,下次打开应用时…

vue如何实现曲线图

vue如何实现曲线图

使用 ECharts 实现曲线图 在 Vue 项目中安装 ECharts 依赖: npm install echarts --save 引入 ECharts 并创建基础图表组件: <temp…

java如何安装

java如何安装

安装Java的步骤 下载Java开发工具包(JDK) 访问Oracle官方网站或OpenJDK项目页面下载适合操作系统的JDK版本。Oracle JDK适用于商业用途,OpenJDK是开源版本。选择…

php如何实现静态化

php如何实现静态化

PHP 实现静态化的方法 使用 ob_start() 和 ob_get_contents() 利用 PHP 的输出缓冲功能捕获动态生成的页面内容,将其保存为静态文件。这种方法适用于内容不频繁变化的页面…

vue如何实现拖动

vue如何实现拖动

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

java如何自学

java如何自学

确定学习目标和路径 自学Java需要明确目标,例如开发Web应用、Android应用或后端服务。根据目标选择学习重点,如Java基础、Spring框架或Android开发。制定阶段性计划,从基础语法到…