セマフォとスピンロックの基本的な違いは何ですか?
スピンロックでセマフォを使用するのはいつですか?
簡単に言えば、セマフォは「譲歩する」同期オブジェクトであり、スピンロックは「ビジーウェイト」オブジェクトです。(単一のスレッドからコード領域を保護するミューテックス、ガード、モニター、またはクリティカルセクションとは異なり、セマフォは複数のスレッドを同期するという点でもう少しあります)
より多くの状況でセマフォを使用しますが、ロックする時間が非常に短い場合はスピンロックを使用します。特にロックを頻繁に行う場合は、ロックにコストがかかります。このような場合、保護されたリソースがロック解除されるのを待っている間、スピンロックする方が効率的です。回転が長すぎると明らかにパフォーマンスが低下します。
通常、スレッド クォンタムよりも長くスピンする場合は、セマフォを使用する必要があります。
Yoav Aviram と gbjbaanb が言ったことに加えて、もう 1 つの重要なポイントは、シングル CPU マシンでは決してスピンロックを使用しないということでしたが、セマフォはそのようなマシンでは意味があります。最近では、複数のコアやハイパースレッディング、または同等の機能を備えていないマシンを見つけるのに苦労することがよくありますが、CPU が 1 つしかない状況では、セマフォを使用する必要があります。(理由は明らかだと思います。1 つの CPU が他の何かがスピンロックを解放するのを待ってビジーであるが、それが唯一の CPU で実行されている場合、現在のプロセスまたはスレッドがこれにはしばらく時間がかかる可能性があり、プリエンプションが発生するまで何も役に立ちません)。
Rubinni の Linux Device Drivers から
セマフォとは異なり、スピンロックは、割り込みハンドラなど、スリープできないコードで使用できます。
私はカーネルの専門家ではありませんが、ここにいくつかのポイントがあります。
カーネルのコンパイル中にカーネルプリエンプションが有効になっている場合、ユニプロセッサマシンでもスピンロックを使用できます。カーネルのプリエンプションが無効になっている場合、スピンロック (おそらく) はvoidステートメントに展開されます。
また、セマフォとスピンロックを比較しようとしているとき、セマフォはカーネルで使用されているものを指していると思います - IPC (ユーザーランド) で使用されているものではありません。
基本的に、クリティカル セクションが小さく (スリープ/ウェイクアップのオーバーヘッドよりも小さい)、クリティカル セクションがスリープできるものを呼び出さない場合は、スピン ロックが使用されます。クリティカルセクションが大きく、スリープできる場合は、セマフォが使用されます。
ラマン・チャロトラ。
スピンロックとは、マシン依存のアセンブリ命令 (test-and-set など) を使用したスレッド間ロックの実装を指します。これは、スレッドが単純にループ内で待機 (「スピン」) し、ロックが使用可能になる (ビジー待機) まで繰り返しチェックするため、スピンロックと呼ばれます。スピンロックは、(CPU ではなく) オペレーティング システムによって提供される機能であるミューテックスの代わりとして使用されます。
Semaphor は、IPC 用にオペレーティング システムによって提供される機能であり、その主な目的はプロセス間通信です。オペレーティング システムによって提供される機能であるため、そのパフォーマンスはスレッド間ロック用のスピンロックほど良くはありません (可能ではありますが)。セマフォは、長期間のロックに適しています。
そうは言っても、アセンブリにスプリンロックを実装するのは難しく、移植性がありません。
より一般的であり、Linux固有ではありません。
メモリ アーキテクチャとプロセッサの機能によっては、マルチコアまたはマルチプロセッサ システムでセマフォを実装するためにスピンロックが必要になる場合があります。セマフォを取得します。
はい、メモリ アーキテクチャが 1 つのコア/プロセッサによるメモリ セクションのロックを提供し、他のすべてのアクセスを遅らせる場合、およびプロセッサがテスト アンド セットを提供する場合は、スピンロックなしでセマフォを実装できます (ただし、非常に慎重に! )。
ただし、シンプル/安価なマルチコア システムが設計されているため (私は組み込みシステムで作業しています)、すべてのメモリ アーキテクチャがそのようなマルチコア/マルチプロセッサ機能をサポートしているわけではなく、テスト アンド セットまたは同等の機能のみをサポートしています。次に、実装は次のようになります。
セマフォの解放は、次のように実装する必要があります。
はい、OS レベルの単純なバイナリ セマフォの場合は、代わりにスピン ロックのみを使用できます。ただし、保護するコード セクションが非常に小さい場合に限ります。
前述のように、独自の OS を実装する場合は、十分に注意してください。このようなエラーのデバッグは楽しいものですが (多くの人が共有しているわけではありませんが、私の意見です)、ほとんどの場合、非常に退屈で困難です。
「ミューテックス」(または「相互排他ロック」) は、2 つ以上の非同期プロセスが共有リソースを排他的に予約するために使用できるシグナルです。「ミューテックス」の所有権を取得する最初のプロセスは、共有リソースの所有権も取得します。他のプロセスは、最初のプロセスが「ミューテックス」の所有権を解放するのを待ってから、それを取得しようとする必要があります。
カーネルで最も一般的なロック プリミティブはスピンロックです。スピンロックは、非常にシンプルなシングル ホルダー ロックです。プロセスがスピンロックを取得しようとして、それが利用できない場合、プロセスはロックを取得できるまで試行 (スピン) を続けます。この単純さにより、小さくて高速なロックが作成されます。
スピンロックは、スレッドの実行スライス時間が期限切れになる前に、予期した結果がすぐに発生することが確実な場合にのみ使用されます。
例: デバイス ドライバー モジュールでは、ドライバーはハードウェア レジスタ R0 に "0" を書き込み、R0 レジスタが 1 になるのを待つ必要があります。H/W は R0 を読み取り、何らかの作業を行い、R0 に "1" を書き込みます。これは一般に迅速です (マイクロ秒単位)。回転は、H/W によって中断されてスリープ状態になるよりもはるかに優れています。もちろん、回転中はH/Wの故障状態に注意が必要です!
ユーザー アプリケーションがスピンする理由はまったくありません。意味がありません。何らかのイベントが発生するためにスピンする予定であり、そのイベントは別のユーザーレベルのアプリケーションによって完了する必要があり、短い時間枠内で発生することが保証されていません. というわけで、ユーザーモードではまったく回転しません。ユーザーモードでsleep()またはmutexlock()またはsemaphore lock()を使用することをお勧めします。