26

私はそのような構成を使用しています:

  • .NET Framework 4.5
  • Windows Server 2008 R2
  • HP DL360p Gen8(2 * Xeon E5-2640、x64)

私は私のプログラムのどこかにそのようなフィールドを持っています:

protected int HedgeVolume;

いくつかのスレッドからこのフィールドにアクセスします。私はマルチプロセッサシステムを使用しているため、このスレッドが異なるプロセッサで実行されている可能性があると思います。

このフィールドを使用するときはいつでも、最新の値が「読み取り」であることを保証するにはどうすればよいですか?そして、値を「書き込む」ときに、他のすべてのスレッドですぐに使用できるようにするために?

私は何をすべきか?

  • フィールドはそのままにしておきます。
  • それを宣言するvolatile
  • クラスを使用Interlockedしてフィールドにアクセスする
  • .NET 4.5 Volatile.ReadVolatile.Writeフィールドにアクセスするためのメソッドを使用します
  • 使用するlock

この構成でプログラムを動作させるための最も簡単な方法が必要なだけです。別のコンピューター、サーバー、またはオペレーティングシステムでプログラムを動作させる必要はありません。また、待ち時間を最小限に抑えたいので、この標準構成(multiprocessor intel x64、.net 4.5)で常に機能する最速のソリューションを探しています。

4

8 に答える 8

8

あなたの質問には重要な要素が 1 つ欠けています... そのフィールドのデータの整合性はどのくらい重要ですか?

volatileパフォーマンスは向上しますが、スレッドが現在フィールドに変更を書き込んでいる場合、それが完了するまでそのデータを取得できないため、古い情報にアクセスして、別のスレッドが現在行っている変更を上書きする可能性があります。データが機密性の高いものである場合、追跡が非常に困難になるバグが発生する可能性があります。ただし、非常に迅速な更新を行っている場合は、値を読み取らずに上書きし、たまに (数ミリ秒) 古いデータを取得しても気にしないでください。

lock一度に 1 つのスレッドのみがフィールドにアクセスできることを保証します。フィールドを書き込むメソッドにのみ配置し、読み取りメソッドをそのままにしておくことができます。欠点は、速度が遅く、別のスレッドがタスクを実行しているときにスレッドをブロックする可能性があることです。ただし、データが有効なままであることは確かです。

Interlockスケジューラーのコンテキスト切り替えから身を守るために存在します。私の意見?それを使用する理由と正確な使用方法を正確に理解していない限り、使用しないでください。それはオプションを提供しますが、優れたオプションには大きな問題が伴います。変数の更新中のコンテキストの切り替えを防ぎます。思ったように動作しない可能性があり、並列スレッドがタスクを同時に実行するのを妨げません。

于 2012-10-30T07:34:37.000 に答える
5

を使用しますVolatile.Read()

x86 で実行しているため、C# でのすべての書き込みは と同等ですVolatile.Write()。これを使用する必要があるのは Itanium のみです。

Volatile.Read()どのスレッドが最後に書き込んだかに関係なく、最新のコピーを確実に取得できます。

ここに素晴らしい記事があります。C# Memory Model Explained

その要約には、

一部のプロセッサでは、コンパイラは揮発性の読み取りと書き込みで特定の最適化を回避する必要があるだけでなく、特別な命令も使用する必要があります。マルチコア マシンでは、コアごとにキャッシュが異なります。プロセッサは、デフォルトでこれらのキャッシュの一貫性を維持することを気にしない場合があり、キャッシュをフラッシュおよびリフレッシュするために特別な命令が必要になる場合があります。

volatileコンパイラによる最適化を停止する必要があること以外に、多くのことが明白であることを願っていますが、プロセッサもあります。

ただし、C# では、揮発性フィールドまたは非揮発性フィールドのどちらに書き込むかに関係なく、すべての書き込みは (Java とは異なり) 揮発性です。したがって、上記の状況は実際には C# では発生しません。揮発性書き込みは、スレッドのキャッシュを更新してから、キャッシュ全体をメイン メモリにフラッシュします。

必要ありませんVolatile.Write()。より信頼できるソースは、Joe Duffy CLR Memory Modelです。ただし、コンパイラによる並べ替えを停止するために必要になる場合があります。

C# の書き込みはすべて揮発性であるため、すべての書き込みはメイン メモリに直接書き込まれると考えることができます。通常の不揮発性読み取りでは、メインからではなく、スレッドのキャッシュから値を読み取ることができます

あなたが必要Volatile.Read()

于 2012-11-01T10:59:46.017 に答える
2

コンカレント・プログラムの設計を開始するときは、次のオプションを優先順に検討する必要があります:

1) 分離: 各スレッドには独自のプライベート データがあります
2) 不変性: スレッドは共有状態を参照できますが、変更されることはありません
3) 変更可能な共有状態: 共有状態へのすべてのアクセスをロックで保護します

(3) に達した場合、実際に必要な速度はどれくらいですか?

競合していないロックを取得するには、10ns ( 10 -8秒) 程度かかります。これは、ほとんどのアプリケーションにとって十分に高速であり、正確性を保証する最も簡単な方法です。

あなたが言及した他のオプションのいずれかを使用すると、ローロックプログラミングの領域に入ります。これは、正しく理解するのが非常に困難です。


並行ソフトウェアの作成方法を学びたい場合は、以下をお読みください。

紹介: Joe Albahari の無料電子書籍- 読むのに約 1 日かかります

聖書: Joe Duffy の "Concurrent Programming on Windows" - 読むのに約 1 か月かかります

于 2012-10-30T07:50:49.940 に答える
0

volatile-悪い、いくつかの問題があります(Joe Duffyのブログを参照)

値を読み取るか、無条件に値を書き込むだけの場合はVolatile.ReadVolatile.Write

更新された値の読み取りとその後の書き込みが必要な場合は、lock構文を使用してください。ただし、クラス機能を使用してロックなしで同じ効果を達成できますがInterlocked、これはより複雑です(CompareExchange読み取り操作以降に変更されていない、つまり読み取り操作以降に値が変更された場合に再試行するロジックを更新していることを確認するためのsが含まれます。読み取り)。

于 2012-10-24T14:08:31.577 に答える
0

あなたが何をするかに依存します。読み取り専用の場合、volatileが最も簡単で、インターロックによりもう少し制御できます。あなたが説明する問題よりもガヌラーであるため、ロックは不要です。Volatile.Read / Writeについてはよくわかりませんが、使用したことはありません。

于 2012-10-24T13:59:09.130 に答える
0

まずここを見てください:揮発性vs.インターロックvs.ロック

揮発性モディファイアは、マルチカーネルCPUに適したオプションです。

しかし、これで十分ですか?これは、新しいHedgeVolume値の計算方法によって異なります。

  • 新しいHedgeVolumeが現在のHedgeVolumeに依存しない場合は、volatileを使用します。

  • ただし、HedgeVolume [x] = f(HedgeVolume [x-1])の場合、新しい値を計算して割り当てるときにHedgeVolumeが変更されないようにするには、スレッドの同期が必要です。この場合、ロックとインターロックの両方のシナリオが適しています。

于 2012-11-05T20:12:01.200 に答える
0

このことから、フィールドに書き込まれた最後の値を読み取れるようにしたいことがわかります。データの sql 同時実行性の問題との類似性を考えてみましょう。フィールドの最後の値を読み取れるようにしたい場合は、アトミックな命令を作成する必要があります。誰かがフィールドに書き込んでいる場合、そのスレッドが書き込みトランザクションを終了するまで、すべてのスレッドを読み取り用にロックする必要があります。その後、そのスレッドのすべての読み取りは安全になります。問題は書くことと同じように読むことではありません。あなたが私に尋ねれば、書かれたときはいつでもそのフィールドをロックするだけで十分なはずです...

于 2012-11-05T08:49:52.933 に答える
0

同様の質問があり、この記事が非常に役立つことがわかりました。非常に長い読み物ですが、たくさんのことを学びました!

于 2012-11-06T04:25:16.410 に答える