5

特定のサービスが開始されたシステムの一部のセクションに通知するブール値が必要です。同期されたオブジェクトはnotifyAll()の前にスレッドによってロックされません

私はエラーjava.lang.IllegalMonitorStateException: object not locked by thread before notifyAll()を取得しているいくつかの奇妙な理由があります。

奇妙なのは、notifyAll()が、notifyAll()を呼び出すオブジェクトを制御する同期ブロックの内部にあることです。

私のクラスには、次のように起動します:

public class MyService { 

    public static Boolean notifier = Boolean.valueOf(false); 

    @Override 
    public void start() { 
     synchronized (MyService.notifier) { 
      MyService.notifier = Boolean.valueOf(true); 
      MyService.notifier.notifyAll(); 
     } 
    } 

    @Override 
    public void stop() { 
     synchronized (MyService.notifier) { 
      MyService.notifier = Boolean.valueOf(false); 
      MyService.notifier.notifyAll(); 
     } 
    } 
    ... 
} 

私はアンドロイドのアプリケーションに取り組んでいます。私はそれが何かに影響を与えるとは思わないが、私はJavaが動作する方法に影響する場合にそのコメントで質問を補完している。

オブジェクトが同期ブロック内でロックされていると、例外が発生するのはなぜですか?

+1

[このような質問]を見てください(http://stackoverflow.com/questions/260337/why-does-synchronized-notifyall-result-in-a-illegalmonitorstateexception?rq=1) –

+3

モニターが属しているので_field_ではなく_object_に渡します。 'Boolean.FALSE'で同期していますが、' Boolean.TRUE'を通知しています(逆も同様です)。 –

+4

ストーリーのモラルは、変更可能なオブジェクトをロックしないで、finalであることを確認してください。あなたのコードは必要以上に複雑ですが、これを待っているものを見ずに何を置き換えるべきかを提案することはできません。 (それはあなたがそれをすべて削除することができます)私はExecutorServiceがあなたが使用すべきものであると思う。 –

答えて

17

ライン

MyService.notifier = Boolean.valueOf(true); 

スワップアウトあなたがロックオンしているオブジェクトを、それが新しいオブジェクトを参照して、変数を上書きします。ブロックに入ったときにロックを取得したオブジェクトは、notifyAllと同じものではありません。すべてnotifyAllは、それが呼び出されているオブジェクトのロックを取得していないことを知っています。これは、同期ブロックが入力された後に作成された新しいオブジェクトです。

すべてのスレッドは同じロックを使用する必要があります。 Ian Roberts氏のように、ロックはオブジェクトに属します。オブジェクトを上書きすると、新しいロックが発生します。

+0

ありがとうございます。私はそれにこだわりました。 –

+1

@ J-Rou:喜んで助けてください。誰もがしばらくの間立ち往生すると、職業上の危険にさらされます。 –

関連する問題