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