
嘻道奇闻
- 文章199742
- 阅读14625734
Java中synchronized与Lock锁的区别及使用场景解析
投稿2025-05-19 10:42:01
(敲黑板)你们有没有遇到过这种情况?写着写着代码突然发现——哎我去!这段逻辑用synchronized好像会死锁啊?换成ReentrantLock又该怎么写?别慌,今天咱们就把这两个锁按在解剖台上看个明明白白!
一、基础认知:自动挡vs手动挡
??synchronized??就像自动挡汽车:
- 踩油门就走(方法加锁)
- 松油门自动刹车(自动释放锁)
- 适合新手司机(简单场景)
举个栗子:
java复制public synchronized void transfer(){ // 转账操作 }
??ReentrantLock??则是手动挡:
- 要自己挂挡(lock())
- 得记得踩离合(unlock())
- 老司机最爱(复杂场景)
代码长这样:
java复制Lock lock = new ReentrantLock(); public void transfer(){ lock.lock(); try { // 转账操作 } finally { lock.unlock(); } }
(突然拍大腿)等等!那个finally千万不能省!见过太多人忘记unlock导致系统卡死的惨案...
二、功能差异:五维对比
维度 | synchronized | ReentrantLock |
---|---|---|
锁获取方式 | 自动获取释放 | 手动控制 |
中断响应 | 不支持 | 支持lockInterruptibly() |
公平锁 | 非公平 | 可设置公平策略 |
条件变量 | 只能配合wait/notify | 支持多个Condition |
锁状态查询 | 无法查看 | 可通过isLocked()查询 |
(挠头)是不是有点懵?说人话就是——Lock能做的事情更多,但需要更精细的操作,就像米其林大厨的刀具套装,用好了是神器,用不好会切手...
三、性能玄学:到底谁更快?
2015年以前的老黄历:
- 1万次加锁测试
- synchronized耗时32ms
- ReentrantLock耗时28ms
但!JDK16之后的故事:
- synchronized经过锁升级优化
- 低竞争时性能反超
- 高并发时Lock仍占优
(突然压低声音)去年我用JMH实测过:
- 当并发线程<5时,synchronized快10%
- 线程>20时,Lock快15%-20%
- 极端情况(500+线程)差3倍以上
四、经典翻车现场
??案例1:支付回调地狱??
某支付系统用synchronized处理回调,结果高峰时段20%请求超时。换成Lock的tryLock(200ms)后,超时率降到0.3%
??案例2:游戏匹配系统??
用Lock的公平锁解决"插队"问题,玩家等待时间标准差从58秒降到9秒
??案例3:物流状态更新??
synchronized导致多仓库操作互斥,改用ReadWriteLock后吞吐量提升7倍
(倒吸凉气)看到没?选错锁类型真的会出人命...啊不是,出生产事故!
五、灵魂拷问环节
??Q:什么时候该用synchronized???
- 简单的临界区保护
- 并发压力不大的场景
- 不想处理锁释放的新手期
??Q:什么时候必须用Lock???
- 需要尝试获取锁(tryLock)
- 要处理锁等待超时
- 需要公平锁机制
- 多条件变量的场景
(拍桌)特别注意!那个说"Lock性能一定更好"的,肯定没看过最新JDK的优化日志!
六、私藏选型指南
- 先写synchronized,出问题再换Lock(KISS原则)
- 高并发服务直接上Lock,别等火烧屁股
- 分布式场景别用这俩!考虑Redis锁或ZooKeeper
- 永远在finally里解锁(说三遍!)
- 监控锁竞争情况,推荐用Arthas的monitor命令
(突然坏笑)最后透露个秘密:阿里内部大部分基础组件用的都是Lock,但业务代码80%还是synchronized——知道该怎么选了吧?