5

java.util.concurrentクラスのいずれかを使用する場合でも、異なるスレッド間の可視性の問題を回避するために、インスタンスのアクセスを同期する必要がありますか?

質問をもう少し詳しく説明します

java.util.concurrentのインスタンスを使用する場合、1つのスレッドがインスタンスを変更し(つまり、要素を並行ハッシュマップに配置し)、後続のスレッドが変更を認識しない可能性はありますか?

私の質問は、値へのアクセスが同期されていない場合、Javaメモリモデルでは、スレッドがメモリから直接値をフェッチするのではなく、値をキャッシュできるという事実から生じます。

4

2 に答える 2

3

java.util.concurrentパッケージのメモリ整合性プロパティで、パッケージのJavadocAPIを確認できます。

java.util.concurrentとそのサブパッケージのすべてのクラスのメソッドは、これらの保証をより高いレベルの同期に拡張します。特に:

  • オブジェクトを同時コレクションに配置する前のスレッド内のアクションが 発生します-別のスレッド内のコレクションからその要素にアクセスまたは削除した後のアクションの前に発生します。
    [...]

  • Lock.unlock、Semaphore.release、
    CountDownLatch.countDownなどのシンクロナイザーメソッドを「解放」する前のアクションは、Lock.lock、Semaphore.acquire、Condition.await、CountDownLatchなどの「取得」メソッドが成功した後のアクション
    の前に発生します。 。別のスレッドの同じシンクロナイザーオブジェクトで待機します。
    [...]

したがって、このパッケージのクラスは、スレッド制御(、、など)に一連のクラスを使用して、並行性を確認しLockますSemaphore。このクラスは、プログラムで発生前のロジックを処理します。つまり、並行スレッドのFIFOスタックを管理し、現在のスレッドと後続のスレッドをロックおよび解放します(つまり、Thread.wait()およびThread.resume()などを使用します)。

次に、(理論的には)このクラスにアクセスするステートメントを同期する必要はありません。これは、ステートメントがプログラムで同時スレッドアクセスを制御しているためです。

于 2010-10-28T06:54:02.543 に答える
0

たとえば、ConcurrentHashMapは同時コンテキストから使用するように設計されているため、それ以上同期する必要はありません。実際、そうすることで、それが導入する最適化が損なわれる可能性があります。

たとえば、Collections.synchronizedMap(...)は、マップスレッドを安全にする方法を表します。私が理解しているように、これは基本的に、synchronizedキーワード内のすべての呼び出しをラップすることによって機能します。一方、ConcurrentHashMapのようなものは、コレクション内の要素間で同期された「バケット」を作成し、よりきめ細かい同時実行制御を引き起こし、したがって、頻繁な使用下でのロックの競合を少なくします。たとえば、読み取りをロックしない場合もあります。これを同期アクセスで再度ラップすると、これを損なう可能性があります。明らかに、コレクションへのすべてのアクセスが同期されるなど、新しいライブラリのもう1つの利点であることに注意する必要があります。心配する必要はありません(同じくらい!)。

java.lang.concurrentコレクションは、syncrhonisedを介してスレッドセーフを実装する場合があります。その場合、言語仕様は可視性を保証します。彼らはロックを使わずに物事を実行するかもしれません。これについてははっきりしていませんが、ここでも同じ可視性が得られると思います。

コードで更新が失われたように見える場合は、それが単なる競合状態である可能性があります。ConcurrentHashpMapのようなものは、読み取りで最新の値を提供し、書き込みはまだ書き込まれていない可能性があります。多くの場合、精度とパフォーマンスの間のトレードオフになります。

ポイントは; java.util.concurrentはこのようなことを行うことを目的としているので、可視性を確保し、揮発性および/または追加の同期の使用は必要ないはずです。

于 2010-10-28T07:39:36.617 に答える