如何理解Java Thread中的wait和notify方法?

时间:2012-01-01 07:27:12

标签: java multithreading locking wait notify

我对这两个描述非常困惑:

  1. “wait方法阻止调用线程并放弃监视器锁定”
  2. “通知方法取消阻止一个等待线程但不放弃监视器锁定”
  3. 以下是我的问题:

    1. 我知道Java中的每个对象都有一个锁,但“监视器锁”是什么意思?是否与oject的锁相同?

    2. 为什么通知方法需要放弃显示器锁?

    3. 如果我尝试使用以下代码使对象等待:

      class simpleTask extends Thread
      {
          int waitingTime;
      
          public simpleTask(int waitingTime)
          {
              this.waitingTime = waitingTime;
          }
      
          public void run()
          {
              synchronized(this) // this is a reference of current object
              {
              try {
                  this.wait(waitingTime);
              } catch (InterruptedException e) {
              // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }
      }
      
    4. 与上面的第一个描述一样,是指当前对象被synchronized关键字阻塞,然后wait方法释放锁?

3 个答案:

答案 0 :(得分:7)

  

我知道Java中的每个对象都有一个锁,但“监视器锁”是什么意思?它与对象的锁相同吗?

是的,他们是一回事。它们偶尔也被称为对象的“互斥体”和对象的“原始锁定”。 (但是当有人谈到Lock时,他们正在谈论this Java interface ...这是一个不同的锁定机制。)

  

为什么通知方法需要放弃显示器锁?

notify方法不会放弃锁定。在notify调用返回后,您的代码有责任放弃锁定(即保留同步块或从同步方法返回)。

为什么这有必要?因为当前正在等待该锁定的任何其他线程(在wait(...)调用中)必须在wait调用完成之前重新获取该锁定。

他们为什么这样设计notify / wait?这样它们就可以用来实现条件变量。

  

与上面的第一个描述一样,是指当前对象被synchronized关键字阻塞,然后wait方法释放锁?

这是正确的。当一个线程调用someObject.wait()时,someObject上的锁被释放...然后在wait()调用返回之前重新获取(由同一个线程)。当然,与此同时,其他线程已经多次获取并释放了锁someObject 。关键是当wait返回时,调用wait的线程将拥有锁。

答案 1 :(得分:0)

  1. 是的,显示器锁定与对象的锁定相同。如果你synchronized (object),那就是锁定。

  2. 在您的示例中,当前对象在等待时放弃锁定,wait()调用放弃锁定。在另一个线程中,调用notify()来唤醒对象,当wait()调用返回时,它将再次保持锁定。

答案 2 :(得分:0)

A monitor is a type of synchronization construct.

等待放弃锁定的原因是其他线程可以获取锁定,例如可能要等待的其他线程。另外:通常在释放任何线程之前唤醒其他线程锁定的线程,以防止竞争条件。

有关此内容的更多信息,您应该研究条件变量(即condvars)。