能否不使用专用线程正确使用synchronized、wait()和notify()?
Java wait()/notify() 单线程调用挂起问题解析
我编写了一段使用synchronized块、wait()和notify()的Java代码:
public class mutex { private Object mutex = new Object(); public mutex(Object mutex) { this.mutex = mutex; } public void step1() throws InterruptedException { System.out.println("acquiring lock"); synchronized(mutex) { System.out.println("got in sync block"); System.out.println("calling wait"); mutex.wait(); System.out.println("wait finished "); } } public void step2() throws InterruptedException{ System.out.println("acquiring lock"); synchronized(mutex){ System.out.println("got in sync block"); System.out.println("calling notify"); mutex.notify(); System.out.println("notify called"); } } }
测试场景:
- 用两个独立线程分别执行
step1和step2时,程序正常运行并输出预期结果; - 但在同一线程先调用
step1、再sleep后调用step2的场景中,程序调用wait()后直接挂起。
我有以下两个疑问:
- 为何单线程场景会挂起?明明调用
wait()时会释放锁。 - 是否必须使用独立线程才能正确使用
wait()和notify()?
问题1:单线程场景挂起的原因
- 核心逻辑:
wait()会让当前线程释放锁并进入该对象的等待队列,必须由其他线程调用同一对象的notify()/notifyAll()才能唤醒它。 - 在单线程流程里,当执行到
step1中的mutex.wait()时,当前线程直接进入挂起状态,后续的sleep和step2调用根本没有机会执行——线程已经停在wait这一步了,没人能唤醒它,自然会一直挂起。 - 你误以为
wait()释放锁后线程会继续往下走,但实际上wait()是让线程暂停执行,只有其他线程的唤醒信号才能让它从wait()处恢复。
问题2:是否必须用独立线程?
- 是的,
wait()和notify()的设计初衷就是多线程间的协作通信,用来实现线程间的信号传递。 - 单线程环境下使用这两个方法没有任何意义:挂起的线程无法自我唤醒,最终只会陷入永久挂起的状态。只有当存在其他持有同一锁对象的线程,并且该线程调用
notify()/notifyAll()时,等待队列中的线程才有机会被唤醒并继续执行。
内容的提问来源于stack exchange,提问作者Tommaso Pellegrini
相关产品推荐
相关产品推荐

