news 2026/4/3 6:42:41

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/3/31 5:23:51

AI读脸术推理延迟高?CPU绑定与线程优化实战教程

AI读脸术推理延迟高&#xff1f;CPU绑定与线程优化实战教程 1. 为什么“读脸”会卡顿&#xff1a;从现象到根源 你刚启动AI读脸术镜像&#xff0c;上传一张自拍&#xff0c;结果等了3秒才看到方框和标签——这不算快。更糟的是&#xff0c;连续上传5张图&#xff0c;响应时间…

作者头像 李华
网站建设 2026/3/26 8:32:04

保姆级指南:快速部署Qwen3-VL-Reranker-8B多模态重排序服务

保姆级指南&#xff1a;快速部署Qwen3-VL-Reranker-8B多模态重排序服务 你是否遇到过这样的场景&#xff1a; 在图文混合检索系统中&#xff0c;初筛返回了20个候选结果&#xff0c;但真正相关的只有一两个——其余要么语义偏差大&#xff0c;要么风格不匹配&#xff1b; 客服…

作者头像 李华
网站建设 2026/3/31 6:51:49

科哥CV-UNet镜像输出文件命名规则详解

科哥CV-UNet镜像输出文件命名规则详解 在使用科哥开发的 cv_unet_image-matting图像抠图 webui二次开发构建by科哥 镜像时&#xff0c;你可能已经注意到&#xff1a;每次处理完图片后&#xff0c;系统都会自动生成若干文件&#xff0c;并保存在 outputs/ 目录下。但这些文件名…

作者头像 李华
网站建设 2026/3/31 4:13:25

杜绝AI幻觉!WeKnora精准问答系统搭建指南

杜绝AI幻觉&#xff01;WeKnora精准问答系统搭建指南 【免费下载链接】WeKnora LLM-powered framework for deep document understanding, semantic retrieval, and context-aware answers using RAG paradigm. 项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora 你…

作者头像 李华
网站建设 2026/4/1 22:24:03

基于Springboot的民生援助众筹系统的设计与实现

前言 本论文聚焦于设计与实现基于Springboot框架的民生援助众筹系统。在当今社会&#xff0c;民生援助需求日益增长&#xff0c;传统援助方式存在信息不透明、流程繁琐等问题&#xff0c;因此开发该众筹系统具有重要的现实意义。 系统采用Springboot作为核心开发框架&#xff0…

作者头像 李华