2016-10-13 6 views
0

私はシンクロナイゼーションブロックについて学ぶ簡単なプログラムを書いた。プログラムは以下の通りです:プログラムを実行するときJavaでマルチスレッドプログラミングを行っているときにIllegalMonitorStateExceptionを満たす

public class SychronizedBlock { 

    static int balance = 0; 
    static Integer lock = 0; 


    public static void deposit(int amt) { 
     Thread t1 = new Thread(new Runnable() { 
      public void run() { 
       acquire_lock(); 
       int holdings = balance; 
       balance = holdings + amt; 
       System.out.println("deposit " + amt + ", balance: " + balance); 
       release_lock(); 
      } 
     }); 
     t1.start(); 

    } 

    public static void acquire_lock() { 
     synchronized(lock) { 
      while (lock == 1) { 
       try { 
        lock.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      lock = 1; 
     } 
    } 

    public static void release_lock() { 
     synchronized(lock) { 
      lock = 0; 
      lock.notifyAll(); 
     } 
    } 

    public static void test1() { 
     balance = 0; 
     deposit(500); 
     deposit(500); 
    } 

    public static void main(String[] args) { 
     test1(); 
    } 
} 

しかし、私はないIllegalMonitorStateExceptionと会いました。私は、同期ブロック内にwait()とnotifyAll()関数を配置していると思うし、synchronizedのパラメータとしてロックを設定しています。なぜ私はまだ例外を持っていますか?

答えて

0

release_lockメソッドで問題が発生しています。 lock.notifyAll().を呼び出す前にlock0に再割り当てしています。これは、ロックされていない新しいIntegerオブジェクトに対してnotifyAllが呼び出されることを意味します。コードを次のように変更して問題を修正します。

public static void release_lock() { 
    synchronized(lock) {    
     lock.notifyAll(); 
     lock = 0; 
    } 
} 
+1

また、 'lock'変数を変更しないでください。変化する可能性のある変数を同期させることは、めったにありません。 (私はまた、キャッシュ効果のために、ロックのために 'Integer'を使うことを避けたいのですが、私は一般的にその目的のために使用される単純な' Object'をロックする方が好きです) –

+0

それを取得してください!あなたの明確な説明をありがとうございました!私はステートメント "ロック= 0"は、ロックする前に新しいオブジェクトを割り当てることに気付かなかった。 – Tom

+0

そしてあなたの良いアドバイスのためにジョンに感謝! – Tom

関連する問題