3

MyThread クラスのout変数は、このコードで volatile と宣言する必要がありますか、それとも ThreadTest クラスの変数の「揮発性」はstdout引き継がれますか?

import java.io.PrintStream;

class MyThread implements Runnable
{
    int id;
    PrintStream out; // should this be declared volatile?

    MyThread(int id, PrintStream out) {
        this.id = id;
        this.out = out;
    }

    public void run() {
        try {
            Thread.currentThread().sleep((int)(1000 * Math.random()));
            out.println("Thread " + id);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class ThreadTest
{
    static volatile PrintStream stdout = System.out;

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new MyThread(i, stdout)).start();
        }
    }
}
4

4 に答える 4

2

MyThread クラスの out 変数は、このコードで volatile と宣言する必要がありますか、それとも ThreadTest クラスの stdout 変数の「揮発性」が引き継がれますか?

実際に変数の値を渡すため、ボラティリティは「持ち越されません」。

JLS メモリ モデルの仕様を読んだところによると、オブジェクトを作成したスレッドとそれを使用するスレッドの間で同期を介在させず に読み取るには、avolatile 必要です。out

書かれているコードでは、危険にさらされている変数は ですout。これは非プライベート変数であり、クラスにアクセスできるものによってアクセス/更新される可能性があります。あなたの例にはそれを行うコードはありませんが、別のクラスを作成するか、変更することができますThreadTest

しかし、この場合、より良い解決策は次のとおりです。

  • として宣言outfinalます。フィールドセマンティクスはfinal、同期が不要であることを意味します。

  • として宣言outprivateます。これで、スレッドの構築とstart()呼び出しの間の「事前発生」により、可能なアクセスのみoutが正しい値を確認できるようになります。

于 2010-05-29T05:35:39.577 に答える
2

volatile修飾子は実行されず、上記のコードでは何の役にも立ちません。Volatile は、コンストラクターで初期化されると変更されることのない、変数への読み取りと書き込みにメモリ バリアを確立します。同じ理由で、 の volatile 修飾子も何の役にThreadTestも立ちません。

明確にするために、 volatile は、参照されるオブジェクトではなく、変数に適用されます。

于 2010-05-29T05:36:01.387 に答える
0

絶対に引き継がれません。しかし、あなたが何をしようとしているのかはわかりません。 volatile値ではなく、ThreadTest のフィールドを修飾します。

于 2010-05-29T05:32:53.500 に答える
0

は必要ありません。

呼び出し Thread.start の前と呼び出しThread.start の後に作成されたオブジェクトの間には、事前発生があるためです。

于 2011-07-23T10:12:37.723 に答える