2017-01-27 7 views
1

クロスプロセスカウンタが必要です。メモリマップされたファイルの整数をマップしてInterlocked.Incrementを使用することもできますが、Semaphore.Releaseはプログラミングオーバーヘッドが少なくて済みます。例:`Semaphore.Release`をレディメイド連動インクリメントとして使用できますか?

var mySem = new Semaphore(0, int.MaxValue, "mySemName"); 

// Get the next number. 
int num = mySem.Release(); 

これは妥当と思われますか?

+0

@ScottChamberlain、私はそれが正しいとは思わない。 'Release'がインクリメントされ、' WaitOne'が減少します。私はちょうど今LINQPadでそれをテストしました。 –

答えて

2

短い答え:はい

しかし...あなたがインクリメント(またはそれをデクリメント)それを読むために必要があるだろう。スロットの現在の数を読み取るプロパティはありません(これは実際のスロットの意味では意味があります)。

+0

'Release'はカウンタをインクリメントして前の値を返します。 –

+1

@ dan-gphこれが私の主張です。カウンターとして役立つためには、値を変更せずに読むことが必要なのかもしれません。 –

+0

良い点ですが、私の必要に応じて、カウンターを1回読むだけでインクリメントされます。 –

2

"rigmarole"は専門用語です。より少ないオーバーヘッドで?番号

セマフォーは、セマフォーカウンター値がすべてのスレッドにわたって一貫性が保たれるように特別なアルゴリズムを実装しています。カウンター値は検査される前にロックされていなければならず、カウンターの増分または減分が完了するまでロックを保持する必要があります。ロックされている間、他のスレッドは待機(ブロッキングの場合)または単に失敗(非ブロッキングの場合)することがあり、しばらく後に再試行することがあります。

インターロックされたインクリメントは、インクリメント操作がアトミックであることを保証するだけです。インターロックされたバイトの増分は、バイト・インクリメントがCPUレベルの命令であるため、特別なロジックを必要としません。 WordとDWordのインクリメントは、チップセットに応じてアトミックである場合もあれば、アトミックでない場合もあります。それがアトミックであれば、フレームワークはそれを利用し、フレームワークがそれを利用する場合、フレームワークは異なるスレッドが同じワードまたはワード内の異なるメモリ部分を同時にインクリメントしないようにロックを設定します。

ほとんどの場合、インターロックされたインクリメントとデクリメントにはオーバーヘッドがほとんどありません。

+0

ここでプロセッサのオーバーヘッドは気にしません。私はプログラミングオーバーヘッドだけに気をつけます。 –

+3

参照してください。私はリグマロールについてのみ気にしていたと思いました。 –

+0

申し訳ありませんが、私はより正確にすべきでした。私はそれを "プログラミングオーバーヘッド"に変更しました。 –

1

はい、問題なく動作します。しかしこれはSemaphoreクラスが設計されたものではありません。コードを維持するためにあなたの後ろに来る貧しい人をあわててください。彼はSemaphore.WaitOne()呼び出しがどこにあるのか不思議に思います。

この同じことを共有メモリで行うことは難しくありません。ここに必要なものはすべて...

  string mapname = "{EE9D59F3-18F7-4FB6-B76B-AC1E6902BD9B}"; 
      MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(mapname, sizeof(int)); 
      MemoryMappedViewAccessor mmva = mmf.CreateViewAccessor(0, sizeof(int)); 
      int count = Interlocked.Increment(ref *(int*)p.ToPointer()); 

これは誇りに思うコードではありません。/unsafeでコードをコンパイルする必要があります。

エレガントなアプローチがない場合は、デザインの前提を再確認する必要があります。なぜ最初に共有カウンターが必要なのですか?何かをユニークにする場合は、各プロセスでGUIDを生成してみませんか?合計を集計する場合は、サーバーに増分をポストする方が堅牢な方法が考えられます。あなたが本当に高性能のカウントを必要とするなら、おそらくC#はあなたの野望のための正しい手段ではないでしょう。

+0

ありがとうございます。私はピンボケなしにそれを行う方法を見つけることができませんでした。しかし私はセマフォと一緒に行った。私はそれが何をしているのかを説明するためにリリースにコメントを付けました。残念ながら私はデザインについて何もできません。私はただ既存のコードを修正しようとしています。クライアントアプリケーションとWebサービスがあります。どちらもマルチスレッドですが、それを書いた人はスレッドやその危険性を理解していませんでした。それは恐ろしいです。私は物事が望ましい順序から実行されている競合状態を修正しようとしています。これを行うために、私はWebサービスをシングルスレッド化しています。効率は問題ではありません。 ... –

+0

...それを行うために、私は "FIFOミューテックス"クラスを作った。 Windowsが次に行く人を決定する通常のミューテックスとは異なり、待機中のスレッドはFIFO順にキューに入れられます。私はその注文を課すためにグローバルカウンターが必要です(スーパーマーケットのデリカウンターで数字をとるなど)。それはまだひどいですが、私が持っている時間に私ができることは最高です。 –

関連する問題