4

假设我有以下情况:

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()吗?

4

3 回答 3

5

块中notify()调用的位置无关紧要,因为根据定义,如果您仍在块中,那么您仍然持有锁。synchronizedsynchronized

调用 notify() 时不应该立即通知线程吗?

是的。调用notify()将等待队列(等待条件)中的一个线程(如果有)放入阻塞队列(等待锁定)。这确实会立即发生,但被唤醒的线程需要先获得锁才能开始运行。所以它立即被移出等待队列,但仍在等待获得锁。

顺便说一句,我建议把它写成this.wait()并且this.notify()只是为了明确哪个对象受到影响。

于 2012-07-18T15:32:55.123 回答
2

不,notify() 调用在同步块中的位置无关紧要。

我推荐的风格:

class SomeClass {
  synchronized void someMethod() throws InterruptedException{
    ...
    while (! someCondition) {
      wait();
    } 
    ...
  }

  synchronized void someOtherMethod() {
    ...
    makeConditionValid();
    notifyAll();  
  }
}

注意在调用while周围使用循环wait。一些 JVM 会发出虚假通知,因此无法保证在通知线程时,导致它等待的原始条件是有效的。此外,在通知线程放弃锁之前,被唤醒的线程不会运行;所以有可能在等待线程执行时条件再次无效。

于 2012-07-18T15:47:32.353 回答
0

这些调用(即Object#waitObject#notify)需要在同步块中进行。由于您的方法是同步的,因此同步块的范围包括方法内的所有内容。因此,定位与它无关。

于 2012-07-18T15:36:12.963 回答