21

Javaのモニターはインスタンス変数へのアクセスを制限せず、同期宣言されたメソッドまたは同期ステートメントのコードのみにアクセスを制限ますか?

私は2つのスレッドを作成しました.invokesメソッドは同期宣言されていますが、invokesメソッドは同期宣言thread yていません。どちらも共有オブジェクトのメソッドを呼び出します。sync()thread runsync()s

Thread rオブジェクトのモニターまたはロックがまだ によって保持されているs間に、オブジェクトのインスタンス変数を変更できます。thread y

Java のモニターはインスタンス変数へのアクセスを制限せず、同期宣言されたメソッドまたは同期ステートメントのコードのみにアクセスを制限しているのでしょか?

public class Stuff {

    private int a = 10;

    public synchronized void sync() {
        long t1 = System.currentTimeMillis();
        System.out.println("Okay, I am in sync() method. "
                        + "I will be waiting for 10 seconds. Current Time = "
                        + System.currentTimeMillis());
        while (System.currentTimeMillis() - t1 < 10000);
        System.out.println("Okay, I have waited for 10 seconds. Current time is "
                        + System.currentTimeMillis()
                        + ". Now I will exit from sync() method, a = " + this.a);
    }

    public void unsync() {
        System.out.println("Alright, I am in unsync() method. The current time is "
                        + System.currentTimeMillis());
        this.a = this.a + 1;
        System.out.println(". The time of exit from unsync() method is "
                        + System.currentTimeMillis());

    }
}

class T1 extends Thread {

    Stuff s;

    public T1(Stuff s) {
        this.s = s;
    }

    public void run() {
        s.sync();
    }
}

class T2 extends Thread {

    Stuff s;

    public T2(Stuff s) {
        this.s = s;
    }

    public void run() {
        s.unsync();
    }
}

class Main {

    public static void main(String args[]) throws Exception {
        Stuff s = new Stuff();
        T1 y = new T1(s);
        T2 r = new T2(s);
        y.start();
        Thread.sleep(2000);
        r.start();
    }
}

プログラムの出力は以下のとおりです。

 
さて、私はsync()メソッドにいます。10秒待ちます。現在時刻 = 1358801766310  
さて、私は unsync() メソッドにいます。現在の時刻は 1358801768343 です。unsync() メソッドの終了時刻は 1358801768343 です。  
よし、10秒待った。現在の時刻は 1358801776310 です。ここで、sync() メソッドを終了します。a = 11
4

3 に答える 3

18

はい。オブジェクトのモニターを保持すると、別のスレッドが別のコード ブロックを実行したり、同じオブジェクトで同期したりすることができなくなります。メソッドが同期されていない場合、別のスレッドがモニターを保持しているかどうかに関係なく、任意のスレッドがいつでも呼び出すことができます。

少なくとも 1 つのスレッドがこの共有状態を変更する可能性がある場合は、読み取り専用アクセスであっても、共有状態へのすべてのアクセスを同期する必要があります。

于 2013-01-21T21:02:09.843 に答える
3

メソッドを同期すると、次の 2 つの効果があります。

まず、同じオブジェクトに対する同期メソッドの 2 つの呼び出しをインターリーブすることはできません。1 つのスレッドがオブジェクトの同期メソッドを実行している場合、同じオブジェクトの同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトの処理を完了するまでブロック (実行を中断) します。

第 2 に、同期メソッドが終了すると、同じオブジェクトに対する同期メソッドのその後の呼び出しとの先行発生関係が自動的に確立されます。これにより、オブジェクトの状態の変更がすべてのスレッドに表示されることが保証されます。

(出典: Java チュートリアル)

于 2013-01-21T21:16:39.893 に答える
3

javaのモニターはインスタンス変数へのアクセスを制限せず、同期宣言されたメソッドまたは同期ステートメントのコードのみにアクセスを制限しますか?

はい。

同期ブロック (またはメソッド) は、相互に排他的です。これは、ロックとして使用されるオブジェクト (モニター、それを と呼びましょうlock) がそれらのブロックの外で使用されることを妨げません。その場合、同期は実行されません。たとえば、あるスレッドが読み取りまたは書き込みlockを行っているときに、別のスレッドが同期されたブロック内にlockあり、モニターが存在する可能性があります。

変数へのアクセスを制限したい場合は、すべてのアクセスがロックを保持している間に行われることを確認する必要があります (各アクセスで同じである限り、すべてのロック)。

于 2013-01-21T21:01:48.677 に答える