有人在工作时只是要求在同步中包装等待的原因。

老实说,我看不出推理。我理解javadocs所说的 - 线程需要是对象监视器的所有者,但为什么呢?它会阻止哪些问题? (如果它确实是必要的,为什么等待方法不能自己获得监视器?)

我正在寻找一个相当深入的原因,或者可能是对文章的引用。我在一个快速谷歌中找不到一个。

哦,还有,thread.sleep如何比较?

编辑:很棒的答案 - 我真的希望我可以选择不止一个,因为他们都帮助我理解发生了什么。

有帮助吗?

解决方案

如果对象在调用Object.wait()时没有对象监视器,则在释放监视器之前,它将无法访问该对象来设置通知侦听器。相反,它将被视为试图访问同步对象上的方法的线程。

或者换句话说,两者之间没有区别:

public void doStuffOnThisObject()

和以下方法:

public void wait()

在释放对象监视器之前,将阻止这两种方法。这是Java中的一项功能,用于防止对象的状态被多个线程更新。它只会对wait()方法产生意想不到的后果。

据推测,wait()方法未同步,因为这可能会创建Thread在对象上有多个锁的情况。 (请参阅 Java语言规范/锁定更多信息。)多个锁是一个问题,因为wait()方法只会撤消一个锁。如果方法是同步的,那么它将保证只有方法的锁定才会被撤消,同时仍然可以撤消潜在的外部锁定。这将在代码中创建死锁条件。

要回答关于Thread.sleep()的问题,Thread.sleep()不保证满足您正在等待的任何条件。使用Object.wait()和Object.notify()允许程序员手动实现阻塞。一旦发送了满足条件的通知,线程将解除阻塞。例如磁盘读取已完成,线程可以处理数据。 Thread.sleep()将要求程序员轮询条件是否已满足,如果没有则退回睡眠状态。

其他提示

这里有很多好的答案。但是这里只想提一下,使用wait()时其他必须做的就是在一个循环中进行,这取决于你正在等待的情况,以防你看到虚假的唤醒,这在我的经验确实发生过。

等待其他某个线程将条件更改为true并通知:

synchronized(o) {
  while(! checkCondition()) {
    o.wait();
  }
}

当然,这些天,我建议只使用新的Condition对象,因为它更清晰,并且具有更多功能(例如允许每个锁具有多个条件,能够检查等待队列长度,更灵活的计划/中断等等)。

 Lock lock = new ReentrantLock();
 Condition condition = lock.newCondition();
 lock.lock();
 try {
   while (! checkCondition()) {
     condition.await();
   }
 } finally {
   lock.unlock();
 }

}

它需要拥有监视器,因为wait()的目的是释放监视器并让其他线程获取监视器来进行自己的处理。这些方法(wait / notify)的目的是协调对两个线程之间的同步代码块的访问,这两个线程需要彼此执行某些功能。这不仅仅是确保对数据结构的访问是线程安全的,而是协调多个线程之间的事件。

一个典型的例子是生产者/消费者案例,其中一个线程将数据推送到队列,另一个线程消耗数据。消费线程总是要求监视器访问队列,但是一旦队列为空,就会释放监视器。然后,当消费者不再处理时,生产者线程将只能访问该线程。它会在将更多数据推入队列后通知消费者线程,因此它可以重新获得监视器并再次访问队列。

等待放弃显示器,所以你必须让它放弃。通知也必须有监视器。

您希望这样做的主要原因是确保从wait()返回时拥有监视器 - 通常,您正在使用wait / notify协议来保护某些共享资源,并且您希望它等待返回时可以安全地触摸它。与通知相同 - 通常您正在更改内容然后调用notify() - 您希望拥有监视器,进行更改并调用notify()。

如果你做了这样的功能:

public void synchWait() {
   syncronized { wait(); }
}

等待返回时你不会有显示器 - 你可以得到它,但你可能不会得到它。

以下是我对为什么限制实际上是一项要求的理解。我基于C ++监视器实现,我通过组合互斥锁和条件变量做了一段时间。

mutex + condition_variable = monitor 系统中, wait 调用将条件变量设置为等待状态并释放互斥锁。条件变量是共享状态,因此需要锁定它以避免想要等待的线程和想要通知的线程之间的竞争条件。不使用另一个互斥锁来锁定其状态,而是使用现有的互斥锁。在Java中,当即将等待的线程拥有监视器时,互斥锁被正确锁定。

如果有条件说队列为空,则大部分等待完成。

If(queue is empty)
     queue.wait();

让我们假设队列为空。 如果当前线程在检查队列后先占用,那么如果另一个 线程添加少量元素到队列,当前线程将不知道并将等待 州。那是错的。 所以我们应该有像

这样的东西
Synchornized(queue)
{
   if(queue is empty)
          queue.wait();
}

现在让我们考虑如果他们将自己等待为同步的话。正如其中一条评论中已经提到的,它只释放一个锁。这意味着如果在上面的代码中同步wait(),则只释放一个锁。意味着当前线程将等待队列锁定。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top