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

7

我对以下两个描述感到非常困惑:

  1. "wait方法会阻塞调用线程并释放监视器锁"
  2. "notify方法会解除一个等待线程的阻塞,但不会释放监视器锁"

我的问题如下:

  1. I know each object in Java has a lock, but what is the "monitor lock" means? is it the same as the oject's lock?

  2. Why notify method needs to give up the monitor lock?

  3. If I try to make a object waiting with the following code:

    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();
            }
        }
    }
    

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

3个回答

7
我知道Java中的每个对象都有一个锁,但是“监视器锁”是什么意思?它和对象的锁是一样的吗?
是的,它们是同一件事。它们有时也被称为对象的“互斥锁”和对象的“原始锁”。(但是当有人谈论Lock时,他们谈论的是这个Java接口...这是一种不同的锁定机制。)
为什么notify方法需要放弃监视器锁?
notify方法并没有放弃锁。在notify调用返回后,由您的代码负责放弃锁(即离开同步块或从同步方法返回)。
为什么需要这样做?因为任何其他正在等待该锁的线程(在wait(...)调用中)必须重新获取该锁,然后才能完成wait调用。
我为什么要这样设计 notify / wait?这是为了实现条件变量。
像上面的第一种描述一样,这意味着当前对象被同步关键字锁定,然后等待方法释放锁吗?
这是正确的。当线程调用 someObject.wait() 时,它对 someObject 的锁被释放...然后由同一线程重新获取,在 wait() 调用返回之前。当然,在此期间,someObject 的锁可能已经被其他线程多次获取和释放。重点是,当 wait 返回时,调用 wait 的线程将拥有锁。

谢谢你的回答!但是在你的解释中:“当你调用someObject.wait()时,线程对someObject的锁被释放……然后在wait()调用返回之前重新获取”,在wait()调用返回之前,谁会重新获取锁?再次感谢! - Haoming Zhang
@Miles Zhang:如果可用(即其他线程尚未获取它),相同的线程将重新获取它。 - Tudor

0
  1. 是的,监视器锁与对象锁相同。如果您执行 synchronized (object),那就是锁。

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


0

监视器是一种同步构造类型。

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

如果想了解更多信息,您应该学习条件变量(即condvars)。


谢谢!我会了解一些关于条件变量的知识。 - Haoming Zhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接