news 2026/7/4 18:16:52

Java面试必懂!深入解析synchronized关键字的用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java面试必懂!深入解析synchronized关键字的用法

文章目录

  • Java面试必懂!深入解析synchronized关键字的用法 ?
    • 一、什么是`synchronized`?
    • 二、`synchronized`的使用方式
      • 1. `synchronized`修饰实例方法
      • 2. `synchronized`修饰静态方法
      • 3. `synchronized`修饰代码块
      • 4. `synchronized`的关键点
    • 三、`synchronized`的优缺点
      • 优点
      • 缺点
    • 四、面试常见问题
      • 1. `synchronized`和`ReentrantLock`有什么区别?
      • 2. `synchronized`为什么会引起死锁?
      • 3. 如何避免死锁?
      • 4. `synchronized`和`volatile`有什么区别?
    • 五、实战案例
    • 六、总结
    • `
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

Java面试必懂!深入解析synchronized关键字的用法 ?

大家好,我是闫工!今天呢,咱们来聊一个Java面试中绝对绕不开的话题——synchronized关键字。作为一个在Java世界里摸爬滚打多年的“老码农”,我得告诉你们,这个知识点可是线程安全领域的“老祖宗”了。不管是初学还是进阶,掌握它都是你通向高薪offer的必经之路!所以,咱们今天就从基础到高级,再到面试中可能会被问到的各种细节,来一场彻底的解析!


一、什么是synchronized

简单来说,synchronized关键字是用来保证线程安全的。在线程并发的情况下,多个线程同时操作共享资源时,容易出现“脏数据”或者“竞态条件”,这时候就需要用sync来加把锁,让代码块或方法变成“临界区”,每次只能有一个线程进入执行。

听起来有点抽象?没关系,咱们先来看一个经典的例子:银行转账问题。假设A和B两个人同时给C转账100元,那么如果不做任何处理,可能会出现这样的情况:

publicclassBank{privateintbalance=0;publicvoiddeposit(intamount){balance+=amount;// 这里可能有竞态条件!}publicstaticvoidmain(String[]args){Bankbank=newBank();Threadt1=newThread(()->bank.deposit(100));Threadt2=newThread(()->bank.deposit(100));t1.start();t2.start();}}

上面的代码中,deposit方法没有加锁,所以A和B可能同时读取到balance=0,然后都执行balance += 100,结果就是balance变成100而不是200。这就是线程不安全的表现。

那怎么解决呢?很简单,给deposit加上synchronized

publicsynchronizedvoiddeposit(intamount){balance+=amount;}

这样,每次只有一个线程能执行这个方法,问题就解决了!


二、synchronized的使用方式

1.synchronized修饰实例方法

这是最常见的用法。当一个实例方法被synchronized修饰时,锁的对象是调用该方法的那个具体实例(也就是this)。例如:

publicclassCounter{privateintcount=0;publicsynchronizedvoidincrement(){count++;}}

这样,在同一时间只有一个线程可以执行increment()方法。

2.synchronized修饰静态方法

有时候,我们需要对静态方法加锁。比如,一个类级别的计数器:

publicclassStaticCounter{privatestaticintcount=0;publicsynchronizedstaticvoidincrement(){count++;}}

这时候,锁的对象是这个类的Class对象(StaticCounter.class),所以不管有多少个实例,静态方法只有一个共享的锁。

3.synchronized修饰代码块

有时候我们不需要对整个方法加锁,只需要对一部分代码加锁。这时可以用synchronized包裹一个代码块:

publicclassThreadSafeBank{privateintbalance;publicvoidtransfer(intfromAccountId,inttoAccountId,intamount){synchronized(fromAccountId){// 锁住fromAccountId// 执行转账逻辑...}synchronized(toAccountId){// 锁住toAccountId// ...}}}

这样,可以更灵活地控制锁的范围。

4.synchronized的关键点

  • 锁的对象:无论是方法还是代码块,synchronized都是基于对象来加锁的。实例方法用this,静态方法用Class对象,代码块可以用任意对象。
  • 可重入性:同一个线程可以多次获取同一个锁,而不会死锁。比如,一个线程调用了synchronized方法A,然后在方法A里又调用了另一个synchronized方法B,这时候JVM会知道是同一线程,允许进入。

三、synchronized的优缺点

优点

  1. 简单直接:使用起来非常直观,几乎不需要额外配置。
  2. 内置支持:JDK原生支持,不需要引入第三方库。

缺点

  1. 性能问题:在高并发场景下,synchronized的粒度可能太大,导致线程 contention(争用),影响性能。
  2. 灵活性不足:只能提供粗粒度的锁控制,无法像ReentrantLock那样支持公平锁、可中断锁等高级特性。

四、面试常见问题

1.synchronizedReentrantLock有什么区别?

  • 语法层面synchronized是关键字,语法糖;而ReentrantLock是一个类,需要显式调用方法。
  • 功能层面ReentrantLock提供了更多的灵活性,比如支持公平锁、可中断锁等,但使用起来也更复杂。

2.synchronized为什么会引起死锁?

当两个线程互相等待对方释放锁时就会发生死锁。例如:

publicclassDeadlockExample{publicstaticvoidmain(String[]args){Threadt1=newThread(()->{synchronized(String.class){// 锁Atry{Thread.sleep(100);}catch(InterruptedExceptione){}synchronized(Integer.class){// 锁BSystem.out.println("Thread 1 done");}}});Threadt2=newThread(()->{synchronized(Integer.class){// 锁Btry{Thread.sleep(100);}catch(InterruptedExceptione){}synchronized(String.class){// 锁ASystem.out.println("Thread 2 done");}}});t1.start();t2.start();}}

如果t1先拿到锁A,而t2先拿到锁B,那么两个线程都会卡在等待对方释放锁的状态,导致死锁。

3. 如何避免死锁?

  • 按顺序加锁:所有线程都按照固定的顺序获取锁。
  • 使用tryLock()方法:如果无法立即获得锁,则不阻塞当前线程,而是返回一个布尔值表示是否成功。

4.synchronizedvolatile有什么区别?

  • 作用synchronized是关于多线程的互斥与同步;而volatile是关于内存可见性。
  • 粒度synchronized可以控制一段代码块或方法,而volatile只能修饰变量。

五、实战案例

假设我们有一个共享资源池,需要确保每次只有一个线程能获取资源。这时候可以用synchronized来实现:

publicclassResourcePool{privateObjectresource;publicsynchronizedvoidgetResource(){if(resource==null){// 模拟资源加载try{Thread.sleep(100);}catch(InterruptedExceptione){}resource=newObject();System.out.println("Resource created by "+Thread.currentThread().getName());}}publicstaticvoidmain(String[]args){ResourcePoolpool=newResourcePool();Runnabletask=()->pool.getResource();for(inti=0;i<10;i++){newThread(task,"Thread-"+i).start();}}}

这样,所有线程都会排队等待获取锁,从而保证资源只被创建一次。


六、总结

`

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/30 18:13:21

文字变音乐实战:用 Local AI MusicGen 制作80年代复古风BGM

文字变音乐实战&#xff1a;用 Local AI MusicGen 制作80年代复古风BGM 1. 为什么你需要一个“会写歌”的本地AI&#xff1f; 你有没有过这样的时刻&#xff1a;剪完一段复古滤镜的短视频&#xff0c;卡在最后一步——找不到那段恰到好处的80年代合成器BGM&#xff1f;找版权…

作者头像 李华
网站建设 2026/7/1 8:51:53

苹果芯片GPU加速Transformer推理:Metal性能显著提升

利用Metal Performance Shaders实现快速Transformer推理 我们很高兴地宣布&#xff0c;Thinc PyTorch层现已支持Metal Performance Shaders。这使得在苹果芯片Mac的GPU上运行基于spaCy Transformer的流水线成为可能&#xff0c;并将推理速度提升了最高4.7倍。在本文中&#xf…

作者头像 李华
网站建设 2026/7/1 8:52:01

企业自动化文档处理(ADP)核心技术指南

自动化文档处理(ADP)&#xff1a;企业领导者指南 引言&#xff1a;企业为何现在就需要ADP层 企业文档量正呈爆炸式增长&#xff0c;而后台工作流仍被手动路由、数据重复录入和易出错的审批流程所阻塞。财务团队浪费大量时间核对不匹配的发票。当异常堆积时&#xff0c;运营流…

作者头像 李华
网站建设 2026/7/1 5:53:48

中文图像识别新选择,阿里开源模型真实体验报告

中文图像识别新选择&#xff0c;阿里开源模型真实体验报告 最近在做智能客服的图片理解模块&#xff0c;遇到个头疼问题&#xff1a;用户上传的截图里有“微信支付成功页”“淘宝订单详情”“健康码绿码”&#xff0c;但用英文训练的CLIP模型总把“健康码”识别成“green QR co…

作者头像 李华
网站建设 2026/7/3 16:50:07

Qwen-Image-Edit零基础教程:5分钟学会一句话修图魔法

Qwen-Image-Edit零基础教程&#xff1a;5分钟学会一句话修图魔法 1. 你真的只需要5分钟——这不是宣传&#xff0c;是实测结果 你有没有过这样的时刻&#xff1a; 刚拍完一组产品图&#xff0c;客户突然说“背景换成纯白”&#xff1b; 朋友发来一张聚会照&#xff0c;想加个…

作者头像 李华
网站建设 2026/7/1 8:51:59

财务报表打印费时间?RPA自动批量打,不用挨个点打印

RPA自动化打印财务报表的方法安装RPA工具 选择UiPath、Automation Anywhere或Blue Prism等主流RPA平台&#xff0c;下载安装适合企业规模的版本。建议优先考虑提供社区免费版的工具。配置打印流程模板 在RPA开发界面中创建新流程&#xff0c;添加"打开财务系统"、&qu…

作者头像 李华