所以我有一个执行wait()
的java对象,然后另一个线程在同一个对象上执行notifyAll()
。
当我最初尝试这个时,它不起作用。它会抛出一个IllegalMonitorStateException
。
Thread refreshThread = new Thread(new Runnable() {
final Object dirtyLock = new Object();
public void run() {
while(true)
{
try
{
dirtyLock.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
refreshThread.start();
但是,如果我使用以下代码包围while(true)
循环,则可以正常工作。
synchronized(dirtyLock){ /* while loop */ }
现在我必须在通知此线程唤醒的函数中执行此操作。
synchronized(dirtyLock){ dirtyLock.notifyAll(); }
synchronized
是否赋予监视对象的线程所有权?两个不同的线程如何声明同一个监视器的所有权?
P.S。这个问题对某些人来说可能听起来很愚蠢,但我只是想了解这种行为是如何运作的,而不仅仅是盲目编码。
答案 0 :(得分:1)
在拿着显示器之前,你不能等待()。
对于“old-school”Java并发(使用synchronized关键字作为主要工具),它的工作方式如下:
synchronized(obj){...}构造只允许持有监视器的线程属于标记为“synchronized”的块(或方法)中的obj。每次只有一个线程可以容纳obj的监视器。
因此,当线程尝试进入同步块(或方法)时,只有1会成功。正在尝试的任何其他线程都不能进入该块。
因此,根据定义,当您继续执行同步块时,您就是持有obj监视器的线程。
当你点击wait()然后你必须去睡觉,当你这样做时,你放开了显示器。其他线程现在可以尝试获取它。
顺便说一句,我可以看到你正在尝试使用dirtyLock变量。
它已经存在于Java中 - 它位于一个非常棒的并发工具箱中,名为java.util.concurrent(随JDK提供) - 它是该平台的真正亮点之一,你绝对应该使用它,而不是试图从头开始编写代码。您可以在线阅读有关它的负载,或者购买Brian Goetz& amp; amp; amp; amp; amp; amp;共
答案 1 :(得分:1)
简单地说:synchronized(obj) {...}
让你获得obj的监视器,obj.wait()
放弃监视器让其他线程有机会获得监视器,所以你已经得到了监视器可以放弃