2013-03-23 4 views
3

Мой код вызывает у меня проблему.Многопоточная программа в java

Мой код бросает IllegalMonitorStateException в setStr который находится в классе Хоге.

Я изменяю Hoge.class на this в setStr. Мой код правильно закончен!

Но почему это нормально?

public class Sample { 
     static Hoge gh = new Hoge(); 
     static Hoge gh2 = new Hoge(); 

     public static void main(String[] args) { 

      new Thread() { 
       private Hoge h2 = gh; 
       public void run() { 

        System.out.println("start initialize"); 
        h2.setStr("BazzBazz"); 
        System.out.println("end initialize"); 

        System.out.println("start thread 1"); 
        System.out.println(h2.getStr("thread-1")); 
        System.out.println("end thread 1"); 
       } 
      }.start(); 

      new Thread() { 
       private Hoge h2 = gh2; 

       public void run() { 
        System.out.println("start thread 2"); 
        System.out.println(h2.getStr("thread-2")); 
        System.out.println("end thread 2"); 
       } 
      }.start(); 
     } 
    } 

    class Hoge { 
     private String fuga = "fugafuga"; 

     public void setStr(String str) { 
      synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this". 
       fuga = str; 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     String getStr(String suffix) { 
      synchronized(Hoge.class) { 
       return suffix+ fuga; 
      } 
     } 
    } 

ответ

2

Ваш метод setStr должен быть таким:

public void setStr(String str) { 
      synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this". 
       fuga = str; 
       try { 
        Hoge.class.wait();//call wait on Hoge.class 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

Вы должны использовать Hoge.clas.wait() вместо wait(). Зачем?
Потому что, как указано в oracle documentation about wait():

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта.

i.e a thread can't invoke a wait on an object until it owns that object's lock. В противном случае он выкинет IllegalMonitorStateException. Здесь вы приобретаете замок на объекте Class Hoge (i.e Hoge.class), который называется class level lock, но вызывал wait на текущий объект Hoge (this). Таким образом, это привело к IllegalMonitorStateException. Вот почему ваш код работал нормально, когда вы приобрели блокировку на текущем объекте(), потому что wait() в этом случае был вызван на текущий объект (this).

2

Поскольку this в gh и gh2 различны, this является экземпляром Hoge.

Поэтому, когда используется Hoge.class, есть один единственный синхронизированный замок, вместо использования this, который будет использовать два разных замка.

Смежные вопросы