SemaphoreとSemaphoreSlimのどちらを選択すればよいですか?


109

それらのパブリックインターフェイスは似ています。ドキュメントは SemaphoreSlimは、軽量の代替であり、Windowsカーネルのセマフォを使用していないと述べています。 このリソースは、SemaphoreSlimの方がはるかに高速であることを示しています。SemaphoreSlimはどのような状況でセマフォよりも意味がありますか?


1
セマフォは常にジョブをOSに渡します。セマフォが強く争われていなければ、それは比較的高価になり、カーネルの呼び出しは簡単に400ナノ秒かかります。スリムな好意は、最初にシェア変数を使って安価にそれを試み、それがうまくいかなかった場合にのみOSを呼び出します。セマフォを複数のプロセスで共有する必要があるコーナーの場合を除いて、あなたはいつも安いのが好きです。
ハンスパッサント2018年

回答:


64

1つの違いは、SemaphoreSlimシステム全体にわたる可能性がある名前付きセマフォを許可しないことです。これは、SemaphoreSlimをプロセス間同期に使用できないことを意味します。

MSDNのドキュメントには、「待機時間が非常に短いと予想される場合」はSemSlimを使用する必要があることも示されています。これは通常、スリムバージョンの方が多くのトレードオフに対してより軽量であるという考えにうまく適合します。


66
MSが待ち時間が「非常に短い」わけではないときに何が起こるかについて何か書いてほしいと思います。
ジョンレイノルズ

79
...または「非常に短い」という意味
Richard Szalay

9
システムに応じて、Semaphoreで1マイクロ秒、SemaphoreSlimでWaitOneまたはRelease ["C#5.0 in a Nutshell" pgを実行するには1/4マイクロ秒。890]だから、多分それは彼らが非常に短い待ち時間で意味しているのでしょうか?
David Sherret、2013年

2
@dhsto良い参照!しかし、私はリンクされた記事が「共有リソースにアクセスするための待機時間が非常に短い場合」を意味すると思います-つまり、リソースはセマフォコード自体の待機時間を意味するのではなく、長期間排他的に使用されないでしょうか?リソースがロックされている時間に関係なく、セマフォコードは常に実行されます。
culix 2013

4
@culix SemaphoreとSemaphoreSlimのソースを見ると、SemaphoreSlimが「非常に短い」待機にのみ使用される主な理由は、スピン待機を使用しているためだと思います。これは応答性は高くなりますが、CPUを大量に消費するため、瞬間的な応答の重要性が低い長い待機時間では無駄になります。代わりにセマフォがスレッドをブロックします。
r2_118

17

MSDNのドキュメントに違いが説明されています。

一文で:

  • SemaphoreSlimクラスは、待機時間が非常に短いと予想される場合に、単一のプロセス内で待機するために使用できる軽量で高速なセマフォを表します。

1
これに追加するには、アプリケーションがそのSemaphoreにアクセスする必要があるコンピューター上の唯一のプロセスであるすべてのケースでSemaphoreSlimを使用します。
オースティンサルガット

2
@Salgatなんでそんなことをするの?他の回答で概説さSemaphoreSlimれているように、SpinWaitを使用して実装されているため、多くの時間待機すると、CPU時間を大量に浪費します。あなたのプロセスがコンピュータ上の唯一のプロセスである場合、それは良い考えでさえありません。
M.Stramm

MSDNドキュメントから、「SemaphoreSlimクラスは、単一のアプリ内での同期に推奨されるセマフォです。」特別な場合を除いて、1つのプロセスだけがそのセマフォを使用している場合は、デフォルトでSemaphoreSlimを使用する必要があります。言うまでもなく、すべての並行データ型には通常、特別な例外があります。
オースティンサルガット2016

17

SemaphoreSlimはSpinWaitとMonitorに基づいているため、ロックの取得を待機しているスレッドは、別のスレッドに譲る前にロックを取得するために、しばらくの間CPUサイクルを消費しています。それが発生しない場合、OSがスレッドを再度スケジュールすると、スレッドはシステムにコンテキストを切り替えさせ、(いくつかのCPUサイクルを書き込むことによって)再試行します。長時間待機すると、このパターンはかなりの量のCPUサイクルを使い果たします。したがって、このような実装の最良のシナリオは、ほとんどの場合待機時間がなく、ほとんど即座にロックを取得できる場合です。

セマフォはOSカーネルの実装に依存しているため、ロックを取得するたびにかなりのCPUサイクルを費やしますが、その後、スレッドはロックを取得するために必要なだけスリープします。


12

「短時間」論争について:

少なくともSemaphoreSlim MSDNドキュメントには、

SemaphoreSlimクラスは、単一のアプリ内での同期に推奨されるセマフォです。

備考セクションにあります。同じセクションでは、SemaphoreとSemaphoreSlimの主な違いについても説明しています。

SemaphoreSlimは、Windowsカーネルセマフォを使用しないSemaphoreクラスの軽量な代替品です。Semaphoreクラスとは異なり、SemaphoreSlimクラスは名前付きシステムセマフォをサポートしていません。ローカルセマフォとしてのみ使用できます。


1
詳細:[SemaphoreSlim and other locks] use busy spinning for brief periods before they put the thread into a true Wait state. When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transitiondotnet.github.io/docs/essentials/collections/...
マルコ・スッラ

0

私はここでソースコードを見て、これは私が思いついたものです:

  1. SemaphoreとSemaphoreSlimはどちらも、Win32ネイティブハンドルを内部で使用するWaitHandleから派生しています。これが、両方をDispose()する必要がある理由です。したがって、Slimが軽量であるという考えは疑わしいものです。

  2. SemaphoreSlimは内部でSpinWaitを使用しますが、Semaphoreは使用しません。これは、待機時間が長くなることが予想される場合に、セマフォが少なくともCPUを圧迫しないという意味で、より優れた動作をするはずであることを示しています。


2
SemaphoreSlimは、WaitHandleから派生したものではありません。実際には、1つのプロセス内で操作を同期する必要があるタスクで、カーネルスペースプリミティブであるWaitHandleからの派生を排除するという単一の目標で作成されました。
Igor V Savchenko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.