文章目录
- 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的优缺点
优点
- 简单直接:使用起来非常直观,几乎不需要额外配置。
- 内置支持:JDK原生支持,不需要引入第三方库。
缺点
- 性能问题:在高并发场景下,
synchronized的粒度可能太大,导致线程 contention(争用),影响性能。 - 灵活性不足:只能提供粗粒度的锁控制,无法像ReentrantLock那样支持公平锁、可中断锁等高级特性。
四、面试常见问题
1.synchronized和ReentrantLock有什么区别?
- 语法层面:
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.synchronized和volatile有什么区别?
- 作用:
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!
📥免费领取👉 点击这里获取资料
已帮助数千位开发者成功上岸,下一个就是你!✨