java synchronized关键字用法和底层原理

一、synchronized的用法

synchronized关键字用于实现线程同步,确保多个线程在访问共享资源时不会发生数据竞争和不一致的问题。它主要有三种使用方式:

1. 同步实例方法
publicsynchronizedvoidmethod(){// 同步代码}
  • 锁对象是当前实例(this)。
  • 同一个实例的多个线程调用此方法时会互斥。
2. 同步静态方法
publicstaticsynchronizedvoidstaticMethod(){// 同步代码}
  • 锁对象是当前类的 Class 对象(如MyClass.class)。
  • 所有实例的线程调用此方法时都会互斥。
3. 同步代码块
synchronized(lockObject){// 同步代码}
  • 可以灵活指定锁对象(可以是任意对象)。
  • 缩小了同步范围,提高性能。
4. 深入:wait(),notify(),notifyAll()

这三个方法是定义在Object类中的本地方法,必须在一个同步代码块或同步方法内(即已经持有该对象的监视器锁)调用,否则会抛出IllegalMonitorStateException异常。它们与synchronized配合使用,实现线程间的协调(等待/通知机制)。

  • wait(): 使当前线程释放其持有的对象锁,并进入等待状态(WAITING),直到其他线程调用该对象的notify()notifyAll()方法,或被中断。调用后,线程会释放锁
  • notify(): 随机唤醒一个正在等待该对象锁的线程。被唤醒的线程会从等待池移动到阻塞队列(EntryList)中,等待锁释放后重新竞争锁。
  • notifyAll(): 唤醒所有正在等待该对象锁的线程。这些线程都会被移动到阻塞队列中,共同竞争锁。

典型的生产者-消费者模式示例:

publicclassWaitNotifyExample{privatefinalObjectlock=newObject();privatebooleanconditionMet=false;publicvoidconsumer()throwsInterruptedException{synchronized(lock){// 使用while循环防止"虚假唤醒"while(!conditionMet){lock.wait();// 释放lock锁,当前线程进入等待}// 条件满足,执行消费任务System.out.println("Consuming...");conditionMet=false;lock.notifyAll();// 消费完成,通知生产者}}publicvoidproducer()throwsInterruptedException{synchronized(lock){while(conditionMet){lock.wait();// 如果条件已满足,则等待消费者消费}// 生产任务System.out.println("Producing...");conditionMet=true;lock.notifyAll();// 生产完成,通知消费者}}}

关键点:

  1. 总是需要在循环中调用wait()以防止虚假唤醒(Spurious Wakeup),即线程可能在没有被通知、中断或超时的情况下醒来。
  2. wait()会释放锁,而sleep()不会。
  3. 通常更推荐使用notifyAll(),因为notify()是随机唤醒,可能导致某些线程永远无法被唤醒(线程饥饿)。

二、底层原理

synchronized的底层实现依赖于 JVM 内部的监视器锁(Monitor)机制,主要涉及以下概念:

1. 对象头与 Mark Word
  • 在 HotSpot 虚拟机中,每个对象都有一个对象头,其中包含Mark Word(标记字段)。
  • Mark Word 的长度为 32位 或 64位,用于存储对象的哈希码、分代年龄、锁状态标志位等信息。锁的状态就记录在这里。
2. 锁升级的详细过程

为了平衡性能与安全性,JVM 对synchronized进行了优化,引入了锁升级机制。这个过程是单向的:无锁 → 偏向锁 → 轻量级锁 → 重量级锁

  1. 无锁状态 (01)

    • 初始状态,对象刚被创建,尚未有任何线程竞争。
  2. 偏向锁 (Biased Locking) (01)

    • 目的:消除在无竞争情况下的同步开销。假设在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得。
    • 流程
      • 加锁:当一个线程第一次访问同步块时,它会通过 CAS 操作将自己的线程ID写入对象头的 Mark Word。如果成功,则进入偏向模式,锁标志位变为01,且偏向模式标志为1
      • 执行:此后,只要这个线程再次进入同步块,只需检查 Mark Word 中的线程ID是否是自己。如果是,则无需任何同步操作(如CAS、系统互斥)直接执行,极大提升性能。
      • 撤销:一旦出现另一个线程来尝试竞争锁,偏向锁就会撤销(Revoke Bias)。撤销过程需要等待全局安全点(STW),然后检查原持有偏向锁的线程是否仍活跃。如果活跃,则锁升级为轻量级锁;如果已不活跃,则可将对象置为无锁状态,重新偏向新的线程。
  3. 轻量级锁 (Lightweight Locking) (00)

    • 目的:在有多线程竞争,但竞争时间错开(即近乎交替执行)的场景下,避免线程直接进入阻塞,减少用户态到内核态的切换开销。
    • 加锁流程
      • 线程在执行同步块之前,JVM 会先在当前线程的栈帧中创建一个名为锁记录(Lock Record)的空间。
      • 将对象头的 Mark Word 复制到线程的锁记录中(称为 Displaced Mark Word)。
      • 线程尝试通过CAS操作将对象头的 Mark Word 替换为指向其锁记录的指针。
      • 如果成功,当前线程获得锁,锁标志位变为00
      • 如果失败,表示至少有一条线程与当前线程竞争,当前线程会尝试自旋(循环重试CAS操作)来获取锁。
    • 解锁流程
      • 使用 CAS 操作将 Displaced Mark Word 替换回对象头。
      • 如果成功,表示没有竞争发生。
      • 如果失败,表示当前锁存在竞争,锁会膨胀为重量级锁,并在解锁时唤醒等待的线程。
    • 自旋优化:线程不会立即阻塞,而是循环尝试获取锁。避免了线程上下文切换的开销,但会消耗CPU。如果自旋过度(如自旋次数超过阈值,或竞争的线程数过多),锁会直接升级为重量级锁。
  4. 重量级锁 (Heavyweight Locking) (10)

    • 目的:处理高并发、激烈竞争的场景。
    • 流程:当轻量级锁竞争失败后,会膨胀为重量级锁。此时,Mark Word 中存储的是指向一个互斥量(Mutex)的指针,这个互斥量由操作系统内核提供。
    • 所有等待锁的线程都会进入阻塞状态(BLOCKED),不再消耗CPU。锁的获取和释放需要操作系统进行线程的挂起唤醒,这个过程涉及到复杂的用户态到内核态的切换,开销最大。

锁升级状态总结表:

锁状态存储内容标志位适用场景
无锁对象的哈希码、分代年龄等01无竞争
偏向锁持有偏向锁的线程ID、Epoch、分代年龄、偏向模式标志101只有一个线程访问同步块
轻量级锁指向栈中锁记录的指针00多个线程交替访问,低并发竞争
重量级锁指向互斥量(Mutex)的指针10高并发激烈竞争
3. 底层指令
  • 同步代码块通过monitorentermonitorexit指令实现:
    • 进入同步块时执行monitorenter,退出时执行monitorexit(包括正常退出和异常退出)。
  • 同步方法通过方法表中的ACC_SYNCHRONIZED标志标识,JVM通过此标志判断是否需要同步。

三、注意事项

  1. 可重入性synchronized是可重入锁,同一线程可多次获取同一把锁。
  2. 锁对象不能为 null:同步代码块的锁对象不能是null,否则会抛出NullPointerException
  3. 性能考虑
    • 尽量减小同步范围(使用代码块而非整个方法)。
    • 避免锁竞争激烈,否则会升级为重量级锁,降低性能。
  4. Lock的区别
    • synchronized是关键字,JVM 级别实现;Lock是 API 级别实现。
    • Lock更灵活(可中断、超时、公平锁等),但需手动释放锁。
  5. wait/notify使用注意
    • 必须在同步块内调用。
    • 使用while循环检查条件,防止虚假唤醒。
    • 明确锁对象,调用obj.wait()时必须持有obj的锁。

四、示例代码

publicclassSynchronizedExample{privatefinalObjectlock=newObject();privateintcount=0;// 同步实例方法publicsynchronizedvoidincrement(){count++;}// 同步静态方法publicstaticsynchronizedvoidstaticMethod(){// ...}// 同步代码块publicvoiddoSomething(){synchronized(lock){// 同步代码}}}

总结

synchronized是 Java 中最基本的线程同步机制,通过 JVM 的 Monitor 和精细的锁升级策略(偏向锁->轻量级锁->重量级锁)实现了在高性能无竞争场景和高强度竞争场景下的自适应同步。其内置的wait/notify机制为线程间协调提供了基础。使用时需注意锁的范围、竞争情况以及wait/notify的正确用法,以避免性能问题和逻辑错误。对于更复杂的场景,可以考虑java.util.concurrent包中的高级并发工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1200405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免费查文献的网站有哪些 常用免费学术文献获取平台推荐

做科研的第一道坎,往往不是做实验,也不是写论文,而是——找文献。 很多新手科研小白会陷入一个怪圈:在知网、Google Scholar 上不断换关键词,结果要么信息过载,要么完全抓不到重点。今天分享几个长期使用的…

基于学术研究的NMN成分测评,2026年值得入手的NMN品牌+选购避坑指南

《Nature》《Cell》等国际顶刊多项研究已证实,人体衰老的核心根源的是NAD+(烟酰胺腺嘌呤二核苷酸)水平的持续性流失——30岁后体内NAD+以每年8%-12%的速率递减,到45岁时储备量仅为年轻时的50%,直接导致线粒体功能…

综合项目1.22

1 关闭安全软件2 修改主机名 配置光盘镜像 3 测试网络 安装LNMP环境 4配置环境 5设置论坛安装文件 6 安装论坛软件

视频融合平台EasyCVR构建全方位全天候码头海岸线监管体系

随着全球贸易的蓬勃发展,码头海岸线作为国际贸易的重要枢纽,其安全管理和运营效率面临着前所未有的挑战。传统的人工巡检和分散式监控系统已难以满足现代化港口对安全、效率和智能化管理的需求。在此背景下,视频融合平台EasyCVR正成为码头海岸…

谷歌学术搜索使用指南:高效查找学术文献与研究资源的方法技巧

做科研的第一道坎,往往不是做实验,也不是写论文,而是——找文献。 很多新手科研小白会陷入一个怪圈:在知网、Google Scholar 上不断换关键词,结果要么信息过载,要么完全抓不到重点。今天分享几个长期使用的…

【开题答辩全过程】以 基于springboot的日用药品仓库管理系统的设计与实现为例,包含答辩的问题和答案

个人简介 一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等 开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。 感谢大家…

全网最全10个一键生成论文工具,MBA论文写作必备!

全网最全10个一键生成论文工具,MBA论文写作必备! AI 工具助力论文写作,效率与质量双提升 在当前的学术研究和 MBA 学习过程中,论文写作已成为一项不可或缺的任务。随着人工智能技术的发展,越来越多的 AI 工具开始被应…

西屋电气 X 容联七陌:百年品牌售后服务的数字化进阶之路

西屋电气(Westinghouse Electric Corporation)自1886年创立于美国匹兹堡,以“点亮世界”为愿景,历经100多年发展,已成为全球电气与能源领域的标杆企业。其业务覆盖核电、输配电设备、家用电器、环保解决方案等核心领域…

学术搜索入口:高效查找学术资源的便捷平台

做科研的第一道坎,往往不是做实验,也不是写论文,而是——找文献。 很多新手科研小白会陷入一个怪圈:在知网、Google Scholar 上不断换关键词,结果要么信息过载,要么完全抓不到重点。今天分享几个长期使用的…

【技术】从POD创建看Kubernetes源码实现 (五)- kubelet

✍️ 作者:茶水间Tech 🏷️ 标签:#云计算#云原生#kubernetes#容器 📖 前言 ​ kubernetes的模块比较多,架构复杂,代码量更是庞大,看代码比较麻烦,我们从现实场景出发,从…

sci文献检索入口指南:快速掌握SCI文献检索入口及使用方法

做科研的第一道坎,往往不是做实验,也不是写论文,而是——找文献。 很多新手科研小白会陷入一个怪圈:在知网、Google Scholar 上不断换关键词,结果要么信息过载,要么完全抓不到重点。今天分享几个长期使用的…

【开题答辩全过程】以 基于SpringBoot的律师事务所管理系统的设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

【技术】从POD创建看Kubernetes源码实现 (六)- containerd

✍️ 作者:茶水间Tech 🏷️ 标签:#云计算#云原生#kubernetes#容器📖 前言 ​ kubernetes的模块比较多,架构复杂,代码量更是庞大,看代码比较麻烦,我们从现实场景出发,从…

供应链预测科学:机器学习与优化技术

Ping Xu 在亚马逊的供应链优化技术(SCOT)组织中担任预测科学总监,她是今年消费者科学峰会的组织者之一。 她已在亚马逊担任了近 15 年的各种优化和需求预测职务。她于 2005 年在麻省理工学院获得运筹学博士学位后不久,作为全职员工…

2026年DevOps平台全景观察:本土化与云原生双轨并行下的企业选择

2026年DevOps平台全景观察:本土化与云原生双轨并行下的企业选择 随着数字化转型进入深水区,DevOps平台正从单纯的技术工具演变为企业研发效能的战略基础设施。2026年的技术版图上,DevOps领域呈现出明显的本土化与全球化双轨并行态势&#xff…

一文带你上手 Skills:构建可复用的 AI 能力体系

标准化、可复用、渐进式——让 AI 高效完成重复性任务一、 为什么需要 Skills在传统 LLM 使用场景中,我们通常依赖 Prompt 来让模型完成任务,例如:"你是一个项目经理,请根据输入内容生成符合公司规范的周报……"这种方式…

制造业海外社媒代运营服务商:外贸 B2B 营销 + 海外整合营销 + 海外展会推广平台全链路服务

在全球贸易格局深度调整的背景下,中国外贸正稳步复苏并呈现结构性转型态势。海关总署数据显示,2025年前十个月,我国货物贸易出口达22.12万亿元,同比增长6.2%,外贸“逐季回暖”趋势明显。与此同时,共建“一带一路…

高效<|关键词|>指南:提升学术资源检索效率与科研文献获取能力的实用方法

做科研的第一道坎,往往不是做实验,也不是写论文,而是——找文献。 很多新手科研小白会陷入一个怪圈:在知网、Google Scholar 上不断换关键词,结果要么信息过载,要么完全抓不到重点。今天分享几个长期使用的…

搞定100+表迁移 Navicat实战复盘

需求清单: 100张数据表要迁移(还要支持后续动态新增)双链路同步:MySQL到MySQL、MongoDB到PostgreSQL不能写死配置,要能灵活扩展 技术约束: 源环境(塔外)和目标环境(塔…

寻找可靠碳酸镁货源?这些厂家口碑获认可,国外碳酸镁厂家选哪家优质品牌榜单更新

近年来,随着菱镁矿资源精深加工技术的突破,碳酸镁作为功能性无机材料在有色金属冶炼、医药食品、运动防护等领域的应用需求持续增长。然而,市场上游厂家技术水平参差不齐,部分企业存在原料供应不稳定、产品杂质超标…