需要更好地了解Java同步对象行为和IllegalMonitorStateException

时间:2011-12-01 01:29:38

标签: java

所以我有一个执行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。这个问题对某些人来说可能听起来很愚蠢,但我只是想了解这种行为是如何运作的,而不仅仅是盲目编码。

2 个答案:

答案 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()放弃监视器让其他线程有机会获得监视器,所以你已经得到了监视器可以放弃