126

lazySetとのset方法の違いは何AtomicIntegerですか?ドキュメントには、次のことについて多くのことを言うことはありませんlazySet

最終的には指定された値に設定されます。

保存された値はすぐに目的の値に設定されるのではなく、将来的に設定されるようにスケジュールされているようです。しかし、この方法の実際の使用法は何ですか?例はありますか?

4

6 に答える 6

119

「JDK-6275329:アトミッククラスにlazySetメソッドを追加する」から直接引用:

おそらくマスタングの最後の小さなJSR166フォローアップとして、「lazySet」メソッドをAtomicクラス(AtomicInteger、AtomicReferenceなど)に追加しました。これは、非ブロッキングデータ構造を使用してコードを微調整するときに役立つニッチな方法です。セマンティクスは、書き込みが以前の書き込みで並べ替えられないことが保証されていますが、他の揮発性の書き込みまたは同期アクションが発生するまで、後続の操作で並べ替えられる可能性があります(または、他のスレッドに表示されない可能性があります)。

主な使用例は、長期的なガベージ保持を回避するためだけに、非ブロッキングデータ構造のノードのフィールドを無効にすることです。他のスレッドがしばらくの間null以外の値を参照しても無害である場合に適用されますが、構造が最終的にGC可能であることを確認する必要があります。このような場合、nullvolatile-writeのコストを回避することでパフォーマンスを向上させることができます。非参照ベースのアトミックについても、これらの方針に沿って他のいくつかのユースケースがあるため、このメソッドはすべてのAtomicXクラスでサポートされています。

一般的なマルチプロセッサのマシンレベルの障壁の観点からこれらの操作を考えたい人のために、lazySetは先行する店舗と店舗の障壁(現在のプラットフォームでは操作なしまたは非常に安価)を提供しますが、店舗の負荷の障壁はありません(これは通常、揮発性書き込みの高価な部分です)。

于 2009-09-23T19:09:31.933 に答える
17

lazySetは、rmwスレッド間通信に使用できます。これは、xchgがアトミックであるため、可視性に関しては、ライタースレッドプロセスがキャッシュラインの場所を変更すると、リーダースレッドのプロセッサが次の読み取り時にそれを認識します。これは、intelcpuのキャッシュコヒーレンスプロトコルが保証するためです。 LazySetは機能しますが、キャッシュラインは次の読み取り時に更新されます。ここでも、CPUは十分に最新である必要があります。

http://sc.tamu.edu/systems/eos/nehalem.pdf マルチプロセッサプラットフォームであるNehalemの場合、プロセッサには、他のプロセッサがシステムメモリにアクセスするためのアドレスバスを「スヌープ」(盗聴)する機能があります。それらの内部キャッシュに。彼らはこのスヌーピング機能を使用して、内部キャッシュをシステムメモリと他の相互接続されたプロセッサのキャッシュの両方と一貫性のある状態に保ちます。スヌーピングによって、あるプロセッサが別のプロセッサが現在共有状態でキャッシュしているメモリ位置に書き込もうとしていることを検出した場合、スヌーピングプロセッサはキャッシュブロックを無効にし、次に同じメモリ位置にアクセスしたときにキャッシュラインフィルを実行するように強制します。 。

x86cpuアーキテクチャ用のoracleホットスポットjdk->

lazySet == unsafe.putOrderedLong == xchg rw(nehelem intel cpuで20サイクルかかるソフトバリアとして機能するasm命令)

x86(x86_64)では、このようなバリアは、volatileやAtomicLonggetAndAddよりもパフォーマンス面ではるかに安価です。

1つのプロデューサー、1つのコンシューマーキューのシナリオでは、xchgソフトバリアは、プロデューサースレッドのlazySet(sequence + 1)の前に、新しいデータを消費(処理)するコンシューマースレッドコードの前にコード行を強制することができます。コンシューマースレッドは、compareAndSet(シーケンス、シーケンス+ 1)を使用して、プロデューサーシーケンスが正確に1つインクリメントされたことをアトミックにチェックする必要があります。

Hotspotソースコードをトレースして、lazySetからcppコードへの正確なマッピングを見つけました:http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe 。 cpp Unsafe_setOrderedLong->SET_FIELD_VOLATILE定義->OrderAccess:release_store_fence。x86_64の場合、OrderAccess:release_store_fenceはxchg命令を使用するものとして定義されています。

それがjdk7でどのように正確に定義されているかを見ることができます(dougleaはJDK8のいくつかの新しいものに取り組んでいます): http ://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/ linux_x86 / vm / orderAccess_linux_x86.inline.hpp

hdisを使用して、実行中のlazySetコードのアセンブリを逆アセンブルすることもできます。

別の関連する質問があります: xchgを使用するときにmfenceが必要ですか?

于 2013-01-27T22:56:43.283 に答える
12

lazySetの起源と有用性および基礎となるputOrderedの詳細については、http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.htmlを参照してください

要約すると、lazySetは、ストアロードフェンスではなくストアストアとして機能するという意味で、弱い揮発性書き込みです。これは、揮発性セットに使用される非常に高価な命令ではなく、コンパイラによって並べ替えることができないMOV命令にJITコンパイルされたlazySetに要約されます。

値を読み取るときは、常に揮発性の読み取りを実行することになります(いずれの場合もAtomic * .get()を使用)。

lazySetは、単一のライターに一貫した揮発性書き込みメカニズムを提供します。つまり、単一のライターがlazySetを使用してカウンターをインクリメントすることは完全に合法です。同じカウンターをインクリメントする複数のスレッドは、CASを使用して競合する書き込みを解決する必要があります。 incAndGetのAtomic*のカバー。

于 2012-12-24T11:42:44.587 に答える
9

コンカレントアトミックパッケージの概要から

lazySetには、揮発性変数の書き込み(割り当て)のメモリ効果があります。ただし、通常の不揮発性書き込みでは並べ替えの制約を課さない後続の(前ではない)メモリアクションで並べ替えることができます。他の使用状況の中でも、ガベージコレクションのために、ガベージコレクションのために、二度とアクセスされない参照をnullにするときにlazySetが適用される場合があります。

lazySetに興味がある場合は、他の説明も必要です。

アトミックのアクセスと更新のメモリ効果は、Java™言語仕様のセクション17.4に記載されているように、一般に揮発性物質の規則に従います。

getには、揮発性変数を読み取るメモリ効果があります。

setには、揮発性変数の書き込み(割り当て)のメモリ効果があります。

lazySetには、揮発性変数の書き込み(割り当て)のメモリ効果があります。ただし、通常の不揮発性書き込みでは並べ替えの制約を課さない後続の(前ではない)メモリアクションで並べ替えることができます。他の使用状況の中でも、ガベージコレクションのために、ガベージコレクションのために、二度とアクセスされない参照をnullにするときにlazySetが適用される場合があります。

weakCompareAndSetは、変数をアトミックに読み取りおよび条件付きで書き込みますが、発生前の順序付けは作成しないため、weakCompareAndSetのターゲット以外の変数の前後の読み取りおよび書き込みに関して保証はありません。

compareAndSetと、getAndIncrementなどの他のすべての読み取りおよび更新操作には、揮発性変数の読み取りと書き込みの両方のメモリ効果があります。

于 2015-05-26T09:40:19.380 に答える
5

これが私の理解です。間違っている場合は訂正してください。lazySet()「半」揮発性と考えることができます。これは、他のスレッドによる読み取りに関しては基本的に不揮発性変数です。つまり、lazySetによって設定された値は他の人には見えない可能性があります。スレッド。ただし、別の書き込み操作が発生すると(他のスレッドからの場合もあります)、揮発性になります。私が想像できるlazySetの唯一の影響はですcompareAndSet。したがって、を使用する場合lazySet()get()他のスレッドからは古い値を取得する可能性がありますcompareAndSet()が、書き込み操作であるため、常に新しい値を取得します。

于 2011-03-16T15:19:13.183 に答える
2

Re:それをばかにしようとする-

これは、揮発性フィールドを特定のストア(例:ref = null;)操作で揮発性ではないかのように扱う方法と考えることができます。

これは完全に正確ではありませんが、「OK、私は本当に気にしない」と「うーん、少し考えさせてください」のどちらかを決定できれば十分です。

于 2010-04-23T21:20:59.050 に答える