假设我有以下情况:
synchronized void someMethod() {
...
try {
wait();
}catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
...
}
和
synchronized void someOtherMethod() {
...
notify();
}
Thread
首先访问someMethod
,进入wait
,然后someOtherMethod
通知它并返回Runnable
州。方法中notify()
调用的位置是否重要?即使我将notify()
调用放在方法内的不同位置,我也注意到行为没有变化。
在拨打Thread
时,是否应立即通知notify()
?
答案 0 :(得分:5)
notify()
块中synchronized
调用的位置不很重要,因为根据定义,如果您仍然在synchronized
块中,那么您仍然保持锁定。
当发出notify()调用时,不应立即通知线程吗?
是。调用notify()
将等待队列(等待条件)中的一个线程(如果有)放入阻塞队列(等待锁定)。这确实会立即发生,但唤醒线程需要在它开始运行之前获得锁定。所以它立即被移出等待队列,但仍在等待锁定。
顺便说一下,我建议将其写为this.wait()
和this.notify()
,以明确哪个对象受到影响。
答案 1 :(得分:2)
不,同步块中notify()调用的位置无关紧要。
我推荐的风格:
class SomeClass {
synchronized void someMethod() throws InterruptedException{
...
while (! someCondition) {
wait();
}
...
}
synchronized void someOtherMethod() {
...
makeConditionValid();
notifyAll();
}
}
请注意在while
电话周围使用wait
循环。某些JVM可以发出虚假通知,因此无法保证在通知线程时,导致其等待的原始条件有效。此外,在通知线程放弃锁定之前,唤醒线程不会运行;所以有可能在等待线程执行时,条件再次无效。
答案 2 :(得分:0)
这些调用(即Object#wait
和Object#notify
)需要在同步块中进行。由于您的方法是同步的,因此synchronized块的范围包括方法中的所有内容。因此,定位与它无关。