2011-08-16 12 views
18

多くの場合、すべてのスレッドが条件変数を参照できるように、volatileを使用します。参照型の変数にもvolatileが必要ですか?

volatileフィールドは、これまでのコードではすべてprimitive typeです。

objectフィールドにこの問題がありますか?例:

class a { 

    public String str; 

    public List list; 

} 

strとlistにアクセスするスレッドがある場合、「volatile」を追加する必要がありますか?

Objectへの各アクセスはHeapから直接アクセスし、Objectはプリミティブ型のようにキャッシュされません。

そうですか?

答えて

2

volatile keywordを追加して、そのバインドがchangeになっていることをコンパイラに伝えます。そのため、すべてのスレッド

はそれが

それを更新し、変更がある場合、そのlocal cached copyは、オリジナルのものと同じであることを再確認します。プリミティブでは通常、プリミティブの値がインクリメントされるので、通常はそれを見つけることができます。

または異なるスレッドによってデクリメントされます。 Object、特にListは変更されません。

オブジェクトへの参照。あなたは実行時に、同じ変数に

を別のオブジェクトを割り当てている場合、あなたは

を行うことができます。..

+0

リファレンスはプリミティブのようにキャッシュされる可能性がありますか? – Hesey

+0

@Herseyはい、そうです。 pvblivs答えも参照してください。 – Bringer128

+1

私はフィールド(Object o = null;)を持っていますが、コンストラクタの外で初期化されるためfinalに設定することはできませんが、初期化後は決して他の値に変更されません。 null(nullをチェックすることさえできません)...初期化された後にのみ読み込まれます。この場合、何もする必要はありません - そうですか? (複数のスレッドがオブジェクトにアクセスできます) – ycomp

24

あなたは、オブジェクト参照と実際のオブジェクトを区別する必要があります。あなたのフィールドの修飾子が関連する参考

  • 。異なるオブジェクトへの参照を変更すると(つまり、別のStringを参照する)、その変更は別のThreadによって認識されないことがあります。可視性を強化する場合は、finalまたはvolatileを使用する必要があります。

  • ヒープ上の実際のオブジェクトは、フィールド修飾子の影響を受けません。代わりに、あなたはこのオブジェクトの各フィールドは、同じルールに従って、独自のフィールド修飾子によって決定された参照方法(それがない場合は、同時実行スレッドのため視界が施行されていない?volatileまたはfinalある)

だから、答えははい、volatileまたはfinalを追加する必要があります。文体的には、フィールドを最終的にする方がはるかに良いでしょう。これはスレッドと同じ効果がありますが、より強固なステートメントです。このフィールドは変更できません。これがJVMによって無礼にキャッシュされる理由です。また、同じ理由から、volatileと比較して少しのパフォーマンス上の利点があります。Javaは、フィールドが変更されたかどうかを気にする必要はなく、オーバーヘッドを追加する必要もありません。

関連する問題