Java高级面试题:Lock到底比synchronized强在哪?

软件求生 2025-03-10 09:29:45



在 Java 领域混迹多年的老王,最近跳槽到了大厂,面对的是一场高难度的社招面试。

面试官推了推眼镜,微微一笑:

“老王,聊聊 Lock 接口吧,和 synchronized 比,它有什么优势?”

老王心里一紧,手心微微冒汗。这可是高频面试题,自己之前一直用 synchronized,Lock 倒是听说过,但没仔细研究……

他清了清嗓子,脑子里迅速搜索相关知识。为了让自己的回答更有说服力,他决定讲一个自己的亲身经历。

老王的店铺生意:并发中的锁

老王家开了一家超市,店里有个仓库,负责存放饮料、零食等热销商品。

一天,老王雇了两个伙计小张和小李。

小张负责进货,每次都要往仓库加饮料。

小李负责卖货,每次都要从仓库取饮料给顾客。

为了避免小张进货和小李卖货同时操作,导致数据混乱,老王想了个办法:

“仓库门上装一把锁!谁要进仓库,必须先拿到钥匙。”

这样,无论是进货还是卖货,都必须先拿到钥匙,确保同一时间只有一个人操作仓库。

这个钥匙就像 Java 里的 synchronized 关键字,保证了线程安全。

synchronized:老王的第一把锁

起初,老王的锁是传统的老式门锁,只能一个人用,谁先抢到钥匙谁先用,直到操作完成后,才把钥匙还回去。这就像 synchronized 一样:

老王发现,synchronized 用起来很方便,但它有很多局限性,比如:

钥匙不能转让:线程 A 一旦获取锁,不能把锁转交给线程 B,必须等 A 释放后,B 重新抢占。

钥匙是非公平的:谁抢到算谁的,可能新来的伙计比老伙计更容易抢到(非公平锁)。

钥匙不能定时尝试获取:如果仓库门被锁住,其他人只能傻等,不能设定“等 5 秒没抢到就先去干别的”。

不能支持多个条件:进货和卖货的规则不同,但 synchronized 不能精细控制,只能一把锁管到底。

Lock:老王的智能门锁

老王是个喜欢折腾的人,于是他换了个智能门锁,并且给伙计们讲解了新规则:

公平排队:谁先来,谁先进去,不搞突然抢占。

中断等待:如果小张在等仓库太久,可以随时放弃,先去干别的事(响应中断)。

尝试开锁:如果小李尝试打开仓库门但发现有人在里面,就直接走开,而不是死等。

设定超时:如果等了一会儿仓库门还没开,就不等了,去干别的事。

支持多个钥匙:可以为进货和卖货分别配一把钥匙,不互相干扰。

在 Java 里,这把智能锁就对应着 Lock 接口。

Lock 的 4 大优势

1. 让锁更公平

synchronized 默认是非公平锁,新来的线程可能插队。

而 Lock 可以手动设置公平锁,保证先来的线程先获得锁:

2. 等待锁时可以响应中断

synchronized 一旦进入等待状态,不能被中断。

Lock 提供了 lockInterruptibly(),可以在等待锁的时候被中断:

如果线程 A 在等待锁的过程中,发现自己被中断了,就可以提前退出,而不是无休止等待。

3. 尝试获取锁

场景:小李去拿钥匙,发现仓库门被锁住,他想:“算了,我不等了,先去干别的。”

在 Java 里,Lock 提供 tryLock() 方法,让线程尝试获取锁,如果失败,就直接返回,不会阻塞。

还能指定超时时间,例如等 5 秒,5 秒内还没获取到就放弃:

4. 灵活释放锁

synchronized 必须按照先加锁,后解锁的顺序,不能灵活释放。

但 Lock可以在不同方法、不同范围内释放锁,这样可以有更灵活的加锁策略。

总结:两把锁的选择

面试官听完,满意地点点头:“老王,讲得不错。”

老王心里一松,笑着说:“其实这就是我家的仓库管理经验,生活处处是技术啊。”

END

Java 并发编程很重要,Lock 让我们在高并发场景下有更灵活的锁策略。如果你还在用 synchronized,不妨试试 Lock,它的强大一定会让你惊喜!

如果你觉得这篇文章有帮助,记得点赞、分享、收藏!

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

0 阅读:0
软件求生

软件求生

从事软件开发,分享“技术”、“运营”、“产品”等。