知识卡片
等待通知须持锁
内容
wait/notify 必须在 synchronized 内使用,因为语义直接操作对象监视器:调用 wait() 前线程须已是监视器 Owner(否则抛异常),调用后释放 Owner、移入 WaitSet;notify() 把线程从 WaitSet 移入 EntryList,还要重新抢占 Owner 才能继续。它解决的是协作时序,不是互斥本身。
参考来源
- 位置:《Java高并发核心编程.卷2,多线程、锁、JMM、JUC、高并发设计模式》第2章《Java内置锁的核心原理》2.9.3节《wait方法和notify方法的原理》、2.9.6节《需要在synchronized同步块的内部使用wait和notify》(源文件:_epub-src/OEBPS/Text/chapter92.xhtml、chapter95.xhtml)
- 结论依据:原文说明 wait() 会使线程释放监视器 Owner 资格并进入 WaitSet,notify() 把线程从 WaitSet 移到 EntryList 并使其重新竞争 Owner;同时指出这些操作“都和对象锁监视器是相关的”,因此必须先持有该锁才能调用,否则抛出 IllegalMonitorStateException,据此推出本卡结论。
- 原始内容:当线程调用了locko(某个同步锁对象)的wait()方法后,JVM会将当前线程加入locko监视器的WaitSet(等待集)……当前线程会释放locko对象监视器的Owner权利……wait()方法必须在synchronized同步块的内部调用。在当前线程执行wait()方法前,必须通过synchronized()方法成为对象锁的监视器的Owner。