4

次のコードを検討してください。

class Foo {
    java.util.Timer timer = new java.util.Timer();

    void doAction() {
        ...
        timer.schedule(new SomeTimerTask(), 0L);
        ...
    }

    void cancelAction() {
        timer.cancel();
    }
}

メソッドは異なるスレッドから呼び出されます。メソッド doAction() が最初に呼び出されます。

timerフィールドvolatileが別のスレッドから見えるよう に宣言する必要がありますか?

4

5 に答える 5

6

インスタンス変数の重要な状態を操作するなどのsynchronizedメソッドでキーワードを使用することをお勧めします..doAction()cacelAction() timer

volatileキーワードは、揮発性フィールドを各スレッドに反映するために説明したのとほぼ同じように機能しますが、それはすべての操作をまとめてではなく、個別の操作にのみ適用されます。

于 2012-09-05T10:35:42.807 に答える
3

どちらのスレッドもフィールド自体を変更しないため、フィールドを揮発性にする必要はありません。その値は初期化子で一度設定され、その後は変更されません。

メソッドに同期を追加する必要があるかもしれませんがvolatile、この場合、変数の宣言はまったく不要です。使用finalする方がはるかに適切です。

于 2012-09-05T10:35:53.610 に答える
2

Timer クラスは、 javadocによるとスレッドセーフです。

したがって、 であると宣言timerするvolatileだけで十分です。

ただし、timerが他の場所に割り当てられていない場合 (よくあるようです)、より良い解決策は、フィールドを として宣言することfinalです。timerそれ以上の同期を行うことなく、複数のスレッドから変数を安全に使用できることを確認するには、これで十分です。(これは、 JLS セクション 17.5によって具体的に保証されています。)

Timer がスレッドセーフでない場合は、同期されたメソッドまたはブロック (または Locks などを使用して実装された同等のもの) で Timer インスタンスに対してすべてのアクションを実行する必要があります。である、または不十分であると宣言timerするだけでは不十分です。volatilefinal

于 2012-09-05T10:41:26.503 に答える
0

フィールドを as にする必要はありませんが、メソッドvolatileを使用する方が適切synchronizedです。

public void synchronized doAction(){}

public void synchronized cancelAction(){}
于 2012-09-05T10:39:12.300 に答える
0

フィールドを揮発性として宣言しなくても、すべてのスレッドから見えるようになります。変数に関連付けられたvolatileキーワードは、この変数が複数のスレッドによって変更される可能性があるため、ローカルにキャッシュしてはならないことを Java ランタイムに指示します。

于 2012-09-05T10:35:51.060 に答える