それらのパブリックインターフェイスは似ています。ドキュメントは SemaphoreSlimは、軽量の代替であり、Windowsカーネルのセマフォを使用していないと述べています。 このリソースは、SemaphoreSlimの方がはるかに高速であることを示しています。SemaphoreSlimはどのような状況でセマフォよりも意味がありますか?
それらのパブリックインターフェイスは似ています。ドキュメントは SemaphoreSlimは、軽量の代替であり、Windowsカーネルのセマフォを使用していないと述べています。 このリソースは、SemaphoreSlimの方がはるかに高速であることを示しています。SemaphoreSlimはどのような状況でセマフォよりも意味がありますか?
回答:
1つの違いは、SemaphoreSlim
システム全体にわたる可能性がある名前付きセマフォを許可しないことです。これは、SemaphoreSlimをプロセス間同期に使用できないことを意味します。
MSDNのドキュメントには、「待機時間が非常に短いと予想される場合」はSemSlimを使用する必要があることも示されています。これは通常、スリムバージョンの方が多くのトレードオフに対してより軽量であるという考えにうまく適合します。
MSDNのドキュメントに違いが説明されています。
一文で:
SemaphoreSlim
れているように、SpinWaitを使用して実装されているため、多くの時間待機すると、CPU時間を大量に浪費します。あなたのプロセスがコンピュータ上の唯一のプロセスである場合、それは良い考えでさえありません。
SemaphoreSlimはSpinWaitとMonitorに基づいているため、ロックの取得を待機しているスレッドは、別のスレッドに譲る前にロックを取得するために、しばらくの間CPUサイクルを消費しています。それが発生しない場合、OSがスレッドを再度スケジュールすると、スレッドはシステムにコンテキストを切り替えさせ、(いくつかのCPUサイクルを書き込むことによって)再試行します。長時間待機すると、このパターンはかなりの量のCPUサイクルを使い果たします。したがって、このような実装の最良のシナリオは、ほとんどの場合待機時間がなく、ほとんど即座にロックを取得できる場合です。
セマフォはOSカーネルの実装に依存しているため、ロックを取得するたびにかなりのCPUサイクルを費やしますが、その後、スレッドはロックを取得するために必要なだけスリープします。
「短時間」論争について:
少なくともSemaphoreSlim MSDNドキュメントには、
SemaphoreSlimクラスは、単一のアプリ内での同期に推奨されるセマフォです。
備考セクションにあります。同じセクションでは、SemaphoreとSemaphoreSlimの主な違いについても説明しています。
SemaphoreSlimは、Windowsカーネルセマフォを使用しないSemaphoreクラスの軽量な代替品です。Semaphoreクラスとは異なり、SemaphoreSlimクラスは名前付きシステムセマフォをサポートしていません。ローカルセマフォとしてのみ使用できます。
[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 transition
:dotnet.github.io/docs/essentials/collections/...
私はここでソースコードを見て、これは私が思いついたものです:
SemaphoreとSemaphoreSlimはどちらも、Win32ネイティブハンドルを内部で使用するWaitHandleから派生しています。これが、両方をDispose()する必要がある理由です。したがって、Slimが軽量であるという考えは疑わしいものです。
SemaphoreSlimは内部でSpinWaitを使用しますが、Semaphoreは使用しません。これは、待機時間が長くなることが予想される場合に、セマフォが少なくともCPUを圧迫しないという意味で、より優れた動作をするはずであることを示しています。