2013-03-23 71 views
3

我的代码给了我一个问题。java中的多线程程序

我的代码抛出IllegalMonitorStateExceptionsetStr这是在Hoge类。

我改变Hoge.classthissetStr。我的代码正确完成!

但为什么它正常完成?

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()指定:

此方法应该仅由一个线程是 此对象监视器的拥有者来调用。

即一个thread can't invoke a wait on an object until it owns that object's lock。否则它会抛出IllegalMonitorStateException。在这里,您正在获取名为class level lock的Hoge(即Hoge.class)的对象Class的锁定,但在当前对象Hoge()上调用wait。所以这导致了IllegalMonitorStateException。这就是为什么当你获取对当前对象(this)的锁定时,你的代码工作正常,因为在这种情况下wait()在当前对象(this)本身上被调用。

2

由于thisghgh2是不同的,this是霍格的一个实例。

所以当使用Hoge.class时,会有一个同步锁,而不是使用this这将使用两个不同的锁。