2

下記のプログラムをご覧ください

public class TestVolatile implements Runnable {

    public static volatile int counter;
    public static String lock = "lock";

    public static void main(String[] args) {
        Thread t1 = new Thread(new TestVolatile(),"Thread-1");
        Thread t2 = new Thread(new TestVolatile(),"Thread-2");
        t1.start();
        t2.start();
    }

    public void run() {
        synchronized(this) {
            System.out.println(Thread.currentThread()+"-"+counter);
            counter++;
        }
    }
}

このプログラムを複数回実行すると、3 つの異なる結果が得られます。

最初は

スレッド[スレッド-1,5,メイン]-0
スレッド[スレッド-2,5,メイン]-0

2番目は

スレッド[スレッド-1,5,メイン]-0
スレッド[スレッド-2,5,メイン]-1

3番目は

スレッド[スレッド-1,5,メイン]-1
スレッド[スレッド-2,5,メイン]-0

しかし、ロック オブジェクトを「this」から「lock」に変更すると、2 つの異なる結果が得られます。

最初は

スレッド[スレッド-1,5,メイン]-0
スレッド[スレッド-2,5,メイン]-1

2番目は

スレッド[スレッド-1,5,メイン]-1
スレッド[スレッド-2,5,メイン]-0

プログラムを書くときの私の仮定は、どちらの場合でも、両方のステートメントで「カウンター」が決して0になるべきではないということでした。
誰か説明できますか?

4

2 に答える 2

3

2 つの TestVolatile オブジェクトを作成します。「this」キーワードは、スレッドで実行されている TestVolatile オブジェクトを参照します。したがって、最初の例では同じオブジェクトを同期しません。

このようにコードを変更すると、最初の例が機能し始めます。

public static void main(String[] args) {
    TestVolatile testVolatile = new TestVolatile();
    Thread t1 = new Thread(testVolatile,"Thread-1");
    Thread t2 = new Thread(testVolatile,"Thread-2");
    t1.start();
    t2.start();
}
于 2012-04-26T06:23:40.973 に答える
1

おそらく探しているものではありませんが、synchronizedとの使用を避けたい場合volatileは、次のインスタンスを使用する必要がありますAtomicInteger: http://docs.oracle.com/javase/6/docs/api/java/util/並行/原子/AtomicInteger.html

メソッドを使用しgetAndIncrementて、例と同じ動作を示します。

public class TestVolatile implements Runnable {

    public static AtomicInteger counter = new AtomicInteger();
    public static void main(String[] args) {
        Thread t1 = new Thread(new TestVolatile(),"Thread-1");
        Thread t2 = new Thread(new TestVolatile(),"Thread-2");
        t1.start();
        t2.start();
    }

    public void run() {
        System.out.println(Thread.currentThread() + " - " + counter.getAndIncrement());
    }

}
于 2012-04-26T06:35:19.703 に答える