0
import java.util.*;
import java.io.*;
import java.util.regex.*;

class ZiggyTest2 extends Thread{

    String sa;

    public ZiggyTest2(String sa){
        this.sa = sa;
    }

    public void run(){
        synchronized(sa){
            while(!sa.equals("Done")){
                try{
                    sa.wait();
                }catch(InterruptedException is){System.out.println("IE Exception");}
            }
        }

        System.out.println(sa);
    }
}

class Test{
    private static String sa = new String("Not Done");

    public static void main(String[] args){
        Thread t1 = new ZiggyTest2(sa);
        t1.start();

        synchronized(sa){
            sa = new String("Done");
            sa.notify();
        }
    }
}

上記のプログラムを実行すると、次の例外が発生します。

Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notify(Native Method)
        at Test.main(ZiggyTest2.java:35)

いくつかの質問:

  • IllegalMonitorStateException の理由 Test.sa は新しい String オブジェクトに割り当てられているため、sa.notify() が ZiggyTest2 で使用されているものとは異なるロックで呼び出されるため、ZiggyTest2 スレッドが無期限に待機することを期待していました。

  • 上記の例では、wait() と notify() が「sa」オブジェクトで呼び出されます。単独で notify() を呼び出すことと、オブジェクト、つまり sa.wait() と sa.notify() を使用して notify()/wait() を呼び出すことの違いは何ですか?

  • Test クラスでは同期ブロックに sa オブジェクトのロックがあり、sa オブジェクトは静的ですが、ZiggyTest2 クラスでは、同期ブロックは同じ sa オブジェクト参照を使用していますが、静的でない参照を使用していますか? 1 つが静的で、もう 1 つが静的ではない場合、両方とも同じロックを引き続き使用しますか?

4

1 に答える 1

2

実行すると

sa = new String("Done");

文字列参照の内容をによって変更することはありませんsa。新しいStringインスタンス(新しいオブジェクト)をに割り当てますsa。文字列は不変です。それらの値を変更することは不可能です。

これは、sa(最初のオブジェクト: "未完了")で同期してから、新しいオブジェクトをsa(2番目のオブジェクト: "完了")に割り当て、この2番目のオブジェクトでnotifyを呼び出すことを意味します。2番目のオブジェクトでは同期していないので、最初のオブジェクトではIllegalMonitorExceptionが発生します。オブジェクトでnotifyを呼び出すことは、オブジェクトの固有のロックを所有している場合にのみ許可されます。そのため、ロックは常に最終的なものでなければなりません。

notify()を呼び出すことは、this.notify()を呼び出すことと同じです。つまりthis.notify()、2つの異なるオブジェクトsa.notify()を呼び出しているだけです。notify()1つ目は待機中のスレッドthisに通知し、2つ目は待機中のスレッドに通知しますsa

変数が静的であるかどうかは関係ありません。ロックは、その参照ではなく、オブジェクトに関連付けられています。

于 2011-12-26T14:52:32.533 に答える