You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java并发中synchronized、wait/notify及ReentrantLock相关问题咨询

问题1:你的表述存在3处明确错误
  • 错误1:认为阻塞线程会“只要程序仍在运行就会持续尝试访问该同步方法”。实际尝试获取被占用monitor的线程会进入阻塞队列进入休眠状态,不会空转消耗CPU,只有monitor被释放时才会被操作系统唤醒参与锁竞争。
  • 错误2:认为“调用wait()可能会出现多个线程同时处于synchronized块内的情况”。实际wait()被调用的瞬间,当前线程就会主动释放持有的monitor,进入该monitor的等待队列,完全让出执行权限,同一时间永远只有一个线程持有对应monitor的锁、执行synchronized块内的代码。
  • 错误3:认为“必须在块末尾调用notify()来避免线程永久等待”。首先notify()不需要放在块末尾,只要持有锁的期间调用都生效;其次只有使用了wait()挂起线程的场景才需要配套notify()/notifyAll()唤醒,常规synchronized场景线程执行完代码自动释放锁,不需要额外调用notify();另外单调用notify()还可能出现线程饿死问题,多数场景更推荐用notifyAll()。
问题2:synchronized搭配wait()、notify()的常见使用场景
  • 生产者消费者模型:队列满时挂起生产者线程,消费者消费完成后唤醒生产者;队列空时挂起消费者线程,生产者生产完成后唤醒消费者,避免线程空轮询浪费CPU资源。
  • 顺序执行协调:要求多个线程按指定顺序执行任务,比如线程A要先完成初始化操作,线程B才能执行业务逻辑,线程B启动后先调用wait()挂起,线程A完成初始化后调用notify()唤醒线程B继续执行。
  • 状态依赖任务:比如只有连接池存在空闲连接时才能执行数据库查询,无空闲连接时查询线程调用wait()挂起,有连接被归还时唤醒等待的查询线程。
问题3:是否需要直接替换为ReentrantLock这类工具

不需要无脑替换,可以按场景判断:

  • 如果逻辑简单,wait()/notify()的实现逻辑清晰无歧义,完全可以继续用synchronized,它不需要手动释放锁,不容易出现锁泄漏问题,JDK1.6之后做了大量锁优化,性能和ReentrantLock没有明显差距。
  • 如果你的场景需要更灵活的锁能力:比如非阻塞尝试抢锁的tryLock()、可响应中断的锁请求、需要绑定多个条件队列(生产者和消费者分别用独立的Condition,避免notifyAll()唤醒所有线程造成无效竞争),这种时候ReentrantLock的可读性、可维护性会远高于手写wait()/notify()的synchronized代码,替换收益更高。

内容的提问来源于stack exchange,提问作者Spyromancer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:00:01