2013-07-23 43 views
9

我将全局静态对象定义为同步锁。Android java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定

public static Object ConfirmationSynObj = new Object(); 

以下函数是我写的,但它抛出IllegalMonitorStateException。

 synchronized (Config.ConfirmationSynObj) { 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        //this is a http request 
        appSignInfo = getAPKSignature(context, pkinfo.packageName); 
        Config.ConfirmationSynObj.notify(); 
       } 
      }).start(); 
      try { 
       Config.ConfirmationSynObj.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

      if (appSignInfo == null) { 
       return ret; 
      } 
     } 

有谁知道如何锁定对象或函数以防止并发?

+5

请遵循Java命名约定。 –

回答

9

wait/notify一个常见的替换是CountDownLatch 。 (从java.util.concurrent很好,但工作的那种Semaphore逆 - 看到答案由汤姆)

你把它初始化为的步骤所需的量,即已经完成倒计时线程和其他一些地方等待倒计时达到0。

void doFoo() { 
    final CountDownLatch latch = new CountDownLatch(1); 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      //this is a http request 
      appSignInfo = getAPKSignature(context, pkinfo.packageName); 
      latch.countDown(); 
     } 
    }).start(); 
    try { 
     latch.await(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    if (appSignInfo == null) { 
     return ret; 
    } 
} 

但是你写的代码也可以简化为

void doFoo() { 
    return getAPKSignature(context, pkinfo.packageName); 
} 

您启动第二个线程做一些事情,你在这段时间做的是等待。如果在该任务运行时没有任何操作,则不要创建额外的线程。结果是一样的。

如果您尝试在UI线程之外执行HTTP请求,因为您获得了NetworkOnMainThreadExcpeption,则必须以不同的方式执行此操作。虽然Android不会在很长时间内阻止代码,但它仍然会检测到您的代码。例如,使用AsyncTask。

2

您可能正在创建并启动同步块中的线程,但当线程进入Config.ConfirmationSynObj.notify();时,您会注意到没有同步。

您需要在run()中添加一个同步块。

5

@Kayaman说话正确,据我所知,但是如果我可以虚心地建议:java.util.concurrent可以为您节省很多时间!我想用的是semaphore

从文档:“每获得()阻塞,直到许可证可用,然后把它。”。

但也有其他的选择 - 我强烈建议尽可能使用这个,因为你应该避免像你的情况下大量的坑落。

 Semaphore semaphore = new Semaphore(0); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       //this is a http request 
       appSignInfo = getAPKSignature(context, pkinfo.packageName); 
       semaphore.release(); 
      } 
     }).start(); 
     try { 
      semaphore.acquire(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
2
new Thread(new Runnable() { 

      @Override 
      public void run() { 

以上线程不上,因此ConfirmationSynObj对象投掷IllegalMonitorStateException

使用一个更多个同步块内run方法拥有锁定

  @Override 
      public void run() { 
      synchronized (Config.ConfirmationSynObj) { 
       //this is a http request 
       appSignInfo = getAPKSignature(context, pkinfo.packageName); 
       Config.ConfirmationSynObj.notify(); 
       } 
      } 
相关问题