Akira  Noguchi
Akira Noguchi

Reputation: 901

Multithread program in java

My code gives me a problem.

My code throws IllegalMonitorStateException in setStr which is in Hoge class.

I change Hoge.class into this in setStr. My code correctly finished!

But why did it finish normally?

    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;
            }
        }
    }

Upvotes: 3

Views: 768

Answers (2)

Vishal K
Vishal K

Reputation: 13066

YoursetStr method should be like this:

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();
                }
            }
        }

You should use Hoge.clas.wait() instead of wait(). Why?
Because , as specified in oracle documentation about wait() :

This method should only be called by a thread that is the owner of this object's monitor.

i.e a thread can't invoke a wait on an object until it owns that object's lock. Otherwise it will throw IllegalMonitorStateException . Here , you are acquiring lock on object of Class of Hoge(i.e Hoge.class) called as class level lock , but was calling wait on the current object of Hoge(this). So it was leading to IllegalMonitorStateException. That's why your code was working fine when you acquiring lock on the current object (this) because wait() in that case was called on the current object (this) itself.

Upvotes: 2

lichengwu
lichengwu

Reputation: 4307

Because this in gh and gh2 are different, this is an instance of Hoge.

So when use Hoge.class, there is noly one synchronized lock, rather than using this which will use two different lock.

Upvotes: 2

Related Questions