0

フィールドを持つ共有オブジェクトがあるとしましょうdata。複数のスレッドは、フィールドにアクセスするためにこのオブジェクトへの参照を共有します。ただし、スレッドがオブジェクトに同時にアクセスすることはありません。data揮発性として宣言する必要がありますか?

このような状況は次のようになります。

  • クラスCounterは、一意のフィールドvalueと1つのメソッドを定義しincrementます。
  • スレッドはカウンターをインクリメントし、次にカウンターをインクリメントする別のスレッドを生成します。

プログラムのロジックそのものを考えると、カウンターへの同時アクセスはありません。ただし、カウンターは複数のスレッド間で共有されます。カウンターは揮発性でなければなりませんか?

この状況の別の変形は、複数のスレッドがプレーンデータであるオブジェクトXを操作するが、同時実行制御( wait、、)に依存する別のオブジェクトYを介して一時的な実行を交互に行う場合です(Xが同時にアクセスされることはありません)。オブジェクトXのフィールドは揮発性である必要がありますか?notifysynchronize

4

5 に答える 5

3

Javaで同時実行を行う人には、Javaメモリモデルに関するJLSの章全体を学習することを強くお勧めします(実際には必須です)。具体的には、あなたのケースはJLS、17.4.4でカバーされています。

「スレッドを開始するアクションは、スレッド内の最初のアクションと同期します。」

これは、最初のシナリオでは必要がないことを意味しますvolatile。ただし、とにかくコードへの将来の変更に対して堅牢であるようにすることをお勧めします。を持たない正当な理由があるはずですvolatile。これは、読み取り速度が非常に高い場合(少なくとも1秒あたり数百万)の場合にのみ発生します。

于 2012-10-11T11:55:30.917 に答える
1

質問の2番目の部分に関して:変数Xでvolatileを使用しない場合、特定のスレッドが常にローカルにキャッシュされたバージョンの変数の値を使用する可能性があります。変数Yをロックとして使用すると、2つのスレッドがXに同時に書き込みを行わないようにする手段として非常にうまく機能しますが、スレッドの1つが古いデータを参照しないことを保証できません。

JLSから:「揮発性変数vへの書き込みは同期します-任意のスレッドによるvの後続のすべての読み取りと同期します」。私がこれを読む方法は、仕様がv以外の他の変数への読み取りについての保証を提供しないということです。

于 2012-10-11T19:08:47.027 に答える
1

Javaメモリモデルとバイトコードの並べ替えは、後続のスレッドがカウンタの増分値を確認することを保証するものではありません。したがって、単一のスレッドで作業する場合(揮発性物質で何もする必要はありませんが、複数のスレッドが変数から何かを読み取る可能性がある場合)、揮発性物質または同期/ロックのいずれかで別のスレッドへの変更の可視性を確保する必要があります。

Thread.startメソッドはバリアを課すので、可視性が保証されます-そして、その揮発性のものを必要としない場合があります。しかし、とにかくそれを追加します。

于 2012-10-11T11:47:40.213 に答える
0

あなたはカウンターで話の一部を話しただけです。カウンターのインクリメント部分は問題ないようです。Markoが指摘しているように、Thread.startにHBエッジがあります。しかし、誰がこのカウンターを読んでいますか?これらの生成されたスレッド以外の誰かであり、最新の値を表示することにまったく関心がある場合は、フィールドを揮発性にする必要があります。カウンターがlong(またはdouble)の場合、古い値を気にしない場合でも、揮発性である必要があります。そうしないと、単語が途切れてしまう可能性があります。

于 2012-10-11T12:47:33.210 に答える
0

スレッドからの変更は、スレッド間の発生前の関係が確立された場合にのみ、他のスレッドに表示されることが保証されています。関係が確立されると、以前のすべての突然変異が表示されます。

単独で取得したときに正しく同期されないオブジェクトは、別のオブジェクトがそのオブジェクトへのアクセスを正しく同期する場合、安全に使用できます(実際のJava同時実行のpiggibackingを参照)。

質問で説明されている2つのケースでは、同期は必要ないと思います。

オブジェクトXが同時にアクセスされることがないことがわかっている場合は、Xへのアクセスを間接的に同期するオブジェクトYが存在する可能性があるため、問題ありません。私が見る唯一の危険なケースは、スレッドが時間自体を中継して(たとえば、Thread.sleepを使用するか、しばらく時間が経過するまでループすることによって)相互排除を保証する場合です。この場合、確立される前の関係はありません。

于 2013-10-14T06:51:21.003 に答える