java中的多线程程序

时间:2013-03-23 08:32:45

标签: java multithreading

我的代码给了我一个问题。

我的代码会在IllegalMonitorStateException中抛出setStr,这是Hoge类。

我将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 个答案:

答案 0 :(得分:2)

由于thisgh中的gh2不同,this是Hoge的一个实例。

因此,当使用Hoge.class时,只有一个同步锁,而不是使用this,它将使用两个不同的锁。

答案 1 :(得分: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 Hoge(即Hoge.class)的对象的锁定,称为class level lock,但是在wait的当前对象上调用Hoge({ {1}})。所以它导致this。这就是为什么当您获取当前对象(IllegalMonitorStateException)上的锁时,您的代码工作正常,因为在这种情况下this在当前对象(wait())本身上被调用。