2015-09-28 8 views
9

に同期好む私は、次の書面の最後にこのanswerを読んだ:は、揮発性

あなたは揮発性ではない、その逆 シンクロナイズドで行うことができるができる何かを。

明らかではありません。次のようにJLS 8.3.1.4は、揮発性のフィールドを定義:

フィールドは、Javaメモリモデル は、すべてのスレッドが可変 (§17.4)に一貫した値を見ることが保証される場合には、揮発性宣言することができます。

したがって、揮発性フィールドはメモリの可視性に関するものです。また、私が引用した答えからわかる限り、揮発性のフィールドへの読み書きは同期されています。

同期によって、1つのスレッドだけが同期ブロックにアクセスできることが保証されます。私が得たように、それはメモリの可視性とは関係ありません。私は何を取りこぼしたか?

+0

'synchronized'ブロックに入ると終了するとメモリバリアが実行され、変更がスレッド間で見えるようになります。 – Sneftel

答えて

6

は、メモリvisibiltyに関連しています。これにより、同期ブロック内のスレッドによる書き込み結果が、別のスレッドによる読み取りによって保証されることが保証されます。第1スレッドが同期ブロックを終了しました。

注:はPaŭloEbermannさんのコメント@以下、他のスレッドが(例えば同期ブロックに取得することで)読み出しメモリバリアを通過する場合、そのローカルキャッシュが無効化されませんので、彼らは古い値を読み取ることがあります。これらの抽出物のためのhttp://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility

ルック:1つのスレッドによる書き込みの

結果が保証され

同期ブロックの出口がが起こる-前に、このドキュメントではです の読み取り操作の前に、書き込み操作が発生した場合にのみ別のスレッドによって読み取られます。

モニター のアンロック(同期ブロックまたはメソッド出口)が発生し、前と同じモニターのすべての後続のロック(同期ブロックまたはメソッド エントリー)。また、発生前の関係 は推移的であるため、ロックを解除する前のスレッドのすべてのアクションは、 モニターをロックしているすべてのアクションの前に発生します。

+0

優秀な回答、ありがとうございました。メモリの視認性の概念の下では、より一般的な概念があるとは思わなかった。 –

+0

私はこのやや異なって理解するでしょう:同期ブロックの変更(そして実際には前にも)は、後で同じオブジェクトで同期をとる他のスレッドにしか見えません(あるいは、 "後に起こる"他のすべてのスレッドがすべての読み取りを行うわけではありません。 –

+0

@PaŭloEbermann実際に、他のスレッドが同期していない(または何らかの形で読み取りメモリのバリアがある)場合、そのローカルキャッシュは無効にならず、したがって古い値を読み取る可能性があります。 –

1

これは間違っています。同期はメモリの可視性と関係しています。すべてのスレッドには独自のキャッシュがあります。あなたがロックを持っている場合、キャッシュはリフレッシュされます。ロックを解除すると、キャッシュはメインメモリにフラッシュされます。

揮発性フィールドを読み込んだ場合は、リフレッシュもあります。揮発性フィールドを書き込むとフラッシュされます。 JVMは同期ブロックの出口でメモリバリアを追加として実際の同期において

2

同期と揮発性は異なりますが、通常は両方とも同じ共通の問題を解決するために使用されます。

同期化は、特定の時点で共有リソースにアクセスするスレッドが1つだけであることを確認することです。

これらの共有リソースは、しばしばvolatileとして宣言されます。これは、スレッドが共有リソース値を変更した場合、もう一方のスレッドでも更新する必要があるためです。しかし、揮発性のないランタイムは、キャッシュから値を読み取ることによってコードを最適化するだけです。どのような揮発性があるかは、スレッドにアクセスするたびにキャッシュから値を読み取るのではなく、実際に実際のメモリから値を取得し、同じ値が使用されます。


これは私が見つけたものです。

/** 
* Config should be consistent across threads. 
*/ 
protected volatile PrivateConfig config; 
+0

なぜvolatileキーワードを使用するのですか?volatileまたはsynchronizedを指定せずにマルチスレッドアクセスを得ることができます。 –

1

複数のスレッドが共有揮発性変数に書き込むと、彼らはまた、それ以前の値を使用する必要がある場合、それはrace conditionを作成することができます。したがって、この時点では、同期を使用する必要があります。

... 2つのスレッドが共用変数を読み書きしている場合、volatileキーワードを使用するだけでは不十分です。その場合、変数の読み書きが原子的であることを保証するには、synchronizedを使用する必要があります。揮発性変数を読み書きすることは、スレッドの読み書きをブロックしません。これを行うには、クリティカルセクションの周りにsynchronizedキーワードを使用する必要があります。揮発性に関する詳細なチュートリアルについては

'volatile' is not always enoughを参照してください。

+1

[Atomic](http://docs.oracle.com)を使用して、スレッドセーフカウンタやcasのような単純なケース。 com/javase/7/docs/api/java/util/concurrent/atomic/package-summaryにあります。html)型は、通常、より高い競合で、より簡単に実行され、 'synchronized'ブロックよりも優れています。 – duckstep