当前位置: 首页 > news >正文

synchronized锁的原理

synchronized 是 Java 中最基本的锁机制,它的实现原理涉及 对象头Monitor(监视器) 和 JVM 底层机制。以下是 synchronized 的详细原理分析:


1. synchronized 的基本用法

synchronized 可以用于以下三种场景:

  1. 修饰实例方法:锁住当前对象实例。

    public synchronized void method() {
        // 线程安全的代码
    }
  2. 修饰静态方法:锁住当前类的 Class 对象。

    public static synchronized void staticMethod() {
        // 线程安全的代码
    }
  3. 修饰代码块:锁住指定对象。

    public void method() {
        synchronized (this) { // 锁住当前对象
            // 线程安全的代码
        }
    }

2. synchronized 的实现原理

synchronized 的实现依赖于 对象头 和 Monitor 机制

2.1 对象头

在 JVM 中,每个对象都有一个对象头,其中包含以下信息:

  • Mark Word:存储对象的哈希码、锁状态、GC 分代年龄等。

  • Klass Pointer:指向对象的类元数据。

在锁的实现中,Mark Word 是关键部分。它的结构如下:

锁状态存储内容
无锁对象的哈希码、分代年龄等
偏向锁偏向线程 ID、偏向时间戳等
轻量级锁指向栈中锁记录的指针
重量级锁指向 Monitor 对象的指针
GC 标记用于垃圾回收的标记信息
2.2 Monitor 机制

Monitor 是 JVM 实现锁的核心机制。每个对象都与一个 Monitor 关联,Monitor 的主要组成部分包括:

  • Owner:持有锁的线程。

  • EntryList:等待锁的线程队列。

  • WaitSet:调用 wait() 方法后进入等待状态的线程队列。

synchronized 的加锁和解锁过程就是通过操作 Monitor 来实现的。


3. 锁的升级过程

为了提高性能,JVM 对 synchronized 进行了优化,引入了 锁升级 机制。锁的状态会从低到高逐步升级:

  1. 无锁状态:初始状态,没有线程竞争。

  2. 偏向锁:适用于只有一个线程访问同步块的场景。

    • JVM 会将线程 ID 记录在对象头的 Mark Word 中。

    • 如果同一个线程再次请求锁,可以直接获取锁,无需同步操作。

  3. 轻量级锁:当有多个线程竞争时,偏向锁会升级为轻量级锁。

    • 线程会在栈帧中创建锁记录(Lock Record),并将对象头的 Mark Word 复制到锁记录中。

    • 然后尝试通过 CAS 操作将对象头的 Mark Word 替换为指向锁记录的指针。

    • 如果成功,则获取锁;如果失败,则说明存在竞争,升级为重量级锁。

  4. 重量级锁:当竞争激烈时,轻量级锁会升级为重量级锁。

    • 重量级锁依赖于 Monitor 机制,线程会进入阻塞状态,等待锁的释放。


4. synchronized 的加锁与解锁过程

4.1 加锁过程
  1. 线程进入 synchronized 代码块时,JVM 会检查对象头的锁状态。

  2. 如果锁状态为无锁,则尝试通过 CAS 操作获取锁。

  3. 如果锁状态为偏向锁,则检查偏向线程是否为当前线程:

    • 如果是,则直接获取锁。

    • 如果不是,则撤销偏向锁,升级为轻量级锁。

  4. 如果锁状态为轻量级锁,则尝试通过 CAS 操作获取锁:

    • 如果成功,则获取锁。

    • 如果失败,则升级为重量级锁。

  5. 如果锁状态为重量级锁,则线程进入阻塞状态,等待锁的释放。

4.2 解锁过程
  1. 线程执行完 synchronized 代码块后,JVM 会释放锁。

  2. 如果锁状态为偏向锁或轻量级锁,则直接释放锁。

  3. 如果锁状态为重量级锁,则唤醒 EntryList 中的等待线程。


5. synchronized 的优缺点

优点
  • 简单易用,无需手动释放锁。

  • JVM 自动优化锁的升级过程,提高性能。

  • 支持可重入性(同一个线程可以多次获取锁)。

缺点
  • 功能相对简单,不支持超时、中断等高级功能。

  • 在高并发场景下,性能可能不如 ReentrantLock


6. 总结

  • 核心机制synchronized 通过对象头和 Monitor 实现锁的获取与释放。

  • 锁升级:从无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁,逐步升级以提高性能。

  • 适用场景:适合简单的同步场景,高并发场景下可以考虑 ReentrantLock

相关文章:

  • Linux12-UDP\TCP
  • 前端常用的设计模式
  • 工程化与框架系列(21)--前端性能优化(上)
  • SQL 窗口函数之lead() over(partition by ) 和 lag() over(partition by )
  • Unity 实现在模型表面进行绘画
  • Python接口自动化之断言封装!
  • TikTok美国战略升级:聚焦美食旅行,本地化服务如何重塑市场格局
  • 跟着 Lua 5.1 官方参考文档学习 Lua (10)
  • 【SpringBoot】深入解析 Maven 的操作与配置
  • SpringBoot集成Sentry日志收集-1 (Sentry安装)
  • 如何不重启,生效windows环境变量
  • 力扣刷题DAY6(滑动窗口/中等+栈/简单、中等)
  • springboot 集成 MongoDB 基础篇
  • 基于SpringBoot+Vue的校园美食分享平台的设计与实现
  • Redis 脚本:高效数据管理的利器
  • Python 配置文件解析利器:configparser 使用指南
  • 【docker】安装mysql,修改端口号并重启,root改密
  • Android项目优化同步速度
  • 属于网络安全规划重安全性需求
  • 专题02.DeepSeek R1大语言模型发展演进
  • 郑州网站制作公司/google 谷歌
  • 用安卓做网站/搜了网推广效果怎么样
  • 惠阳做网站公司/手机怎么创建自己的网站平台
  • 上海鹭城建设集团网站/山东最新资讯
  • 开发一个b2c网站有哪些困难/泉州百度广告
  • 微信如何做自己的网站/优化设计五年级下册语文答案