スピンロックとセマフォ


119

セマフォとスピンロックの基本的な違いは何ですか?

スピンロックでセマフォを使用するのはいつですか?

回答:


134

スピンロックとセマフォは主に4つの点で異なります。

彼らはどのような1 スピンロックはロックの一つの可能な実装、(「スピン」)ビジーウェイトによって実現され、すなわち1です。セマフォは、ロックの一般化です(または逆に、ロックはセマフォの特殊なケースです)。通常、必須ではありませんが、スピンロックは1つのプロセス内でのみ有効ですが、セマフォを使用して異なるプロセス間で同期することもできます。

ロックは相互排除のために機能します。つまり、一度に1つのスレッドがロックを取得して、コードの「クリティカルセクション」に進むことができます。通常、これは、複数のスレッドで共有される一部のデータを変更するコードを意味します。セマフォはカウンタを持っており、自身がによって買収されることを可能にする一つまたは複数のスレッドを、あなたがそれに投稿するどのような値に応じて、および(一部の実装では)その最大許容値が何であるかに依存します。

これまでのところ、ロックは、最大値が1のセマフォの特殊なケースと考えることができます。

2.それらが行うこと
上記のように、スピンロックはロックであり、したがって相互排他(厳密には1対1)メカニズムです。通常はアトミックな方法で、メモリの場所を繰り返し照会または変更することで機能します。つまり、スピンロックの取得は「ビジー」な操作であり、CPUサイクルを長時間(場合によっては永久に)燃焼させる可能性がありますが、「何もしない」ことになります。
そのようなアプローチの主なインセンティブは、コンテキストスイッチが数百(または数千)回スピンするのと同等のオーバーヘッドを持っているという事実です。そのため、スピンを数回実行してロックを取得できる場合、これは全体的に非常にうまくいく可能性があります。もっと効率的。また、リアルタイムアプリケーションの場合、スケジューラがブロックして、スケジューラが遠く離れた将来に戻ってくるのを待つことは許容できない場合があります。

対照的に、セマフォはまったく回転しないか、非常に短い時間だけ回転します(syscallオーバーヘッドを回避するための最適化として)。セマフォを取得できない場合、セマフォはブロックされ、実行の準備ができている別のスレッドにCPU時間をあきらめます。これはもちろん、スレッドが再度スケジュールされる前に数ミリ秒経過することを意味しますが、これが問題でない場合(通常は問題ありません)、非常に効率的でCPUを節約するアプローチになります。

3.輻輳が発生した場合の動作
スピンロックまたはロックフリーアルゴリズムは「一般に高速」である、または「非常に短いタスク」にのみ役立つと誤解されがちです(理想的には、同期オブジェクトを長時間保持しないでください)絶対に必要以上に)。
重要な違いの1つは、輻輳が存在する場合のさまざまなアプローチの動作です。

適切に設計されたシステムは通常、輻輳が少ないかまったくありません(つまり、すべてのスレッドが同時にロックを取得しようとするわけではありません)。たとえば、通常、ロックを取得し、ネットワークからzip圧縮されたデータの半分のメガバイトをロードし、データをデコードおよび解析して、最後に共有参照を変更するコードを記述しません(データをコンテナーに追加するなど)。ロックを解除する前。代わりに、共有リソースにアクセスする目的でのみロックを取得します。
これは、クリティカルセクションの内側よりも外側にかなり多くの作業があることを意味するため、当然、スレッドがクリティカルセクションの内側にある可能性は比較的低く、同時にロックを争うスレッドはほとんどありません。もちろん、時々2つのスレッドが同時にロックを取得しようとします(これ発生しない場合、ロックは必要ありません!)が、これは「正常な」システムの規則ではなく例外です。 。

このような場合、スピンロックはセマフォよりもはるか優れています。これは、ロックの輻輳がない場合、スピンロックを取得するオーバーヘッドは、コンテキストスイッチの数百/数千サイクルまたは損失の場合1,000〜2,000万サイクルと比較して、ほんの数十サイクルであるためです。タイムスライスの残りの部分。

一方、高い輻輳が発生している場合、またはロックが長期間保持されている場合(場合によっては、それが役に立たないこともあります)、スピンロックは何も実行しないために異常な量のCPUサイクルを消費します。
この場合、セマフォ(またはミューテックス)の方がはるかに優れています。これにより、その間に別のスレッドが有用なタスクを実行できるようになります。または、他に有用なスレッドがない場合は、オペレーティングシステムがCPUを抑制し、熱を減らしてエネルギーを節約できます。

スピニングスレッドが解放するスレッドが予定されていないまで多分これは、(起こることができない状態変化を待ってその完全な時間を無駄になるようまた、シングルコアのシステム上で、スピンロックは、ロック混雑の存在下で、非常に非効率的になりますISN待機中のスレッドの実行中には発生しません!)したがって、何らかの量の競合がある場合、最良の場合(解放スレッドが次にスケジュールされているものと想定)、ロックの取得には約1 1/2のタイムスライスがかかりますが、これはあまり良い動作ではありません。

4.それらの実装方法
セマフォは現在、通常sys_futexLinuxの下でラップします(オプションで、数回の試行後に終了するスピンロックを使用します)。
スピンロックは通常、アトミック操作を使用して実装され、オペレーティングシステムによって提供されるものは使用されません。以前は、これはコンパイラ組み込み関数または移植不可能なアセンブラ命令のいずれかを使用することを意味していました。一方、C ++ 11とC11はどちらも言語の一部としてアトミック操作を備えているため、証明可能な正しいロックフリーコードを書くことの一般的な難しさを除けば、完全にポータブルで(ほぼ)ロックフリーコードを実装することが可能です。痛みのない方法。


「また、シングルコアシステムでは、スピンスレッドは、起こり得ない状態変化を待機するためにその完全な時間を浪費するため、ロックの輻輳が存在する場合、非常に非効率になります」:(少なくともLinuxでは)はspin_trylock、ロックを取得できなかった場合にエラーコードを返します。スピンロックは必ずしもそれほど厳しいものではありません。ただしspin_trylock、アプリケーションの場合、使用するには、その方法で適切に設計する必要があります(おそらく保留中の操作のキューであり、ここでは次の操作を選択して、実際の操作をキューに残します)。
Hibou57 2013

ミューテックスとセマフォのブロックは、シングルスレッド環境で役立つだけでなく、オーバーサブスクリプションがある場合、つまり、プログラム(またはシステムを共有する複数のプログラム)が作成するスレッドの数がハードウェアリソースの数よりも多い場合にも役立ちます。このような場合、スレッドをブロックすると、他のユーザーが便利な方法でCPU時間を使用できるようになります。さらに、ハードウェアがハイパースレッディングをサポートしている場合、他のスレッドはアイドルループの実行に使用されている実行ユニットを利用できます。
ホルヘベロン2017年

76

非常に簡単に言うと、セマフォは「譲歩」する同期オブジェクトであり、スピンロックは「ビジーウェイト」オブジェクトです。(単一スレッドからコード領域を保護するミューテックス、ガード、モニター、またはクリティカルセクションとは異なり、セマフォはいくつかのスレッドを同期するという点でもう少しあります)

あなたはより多くの状況でセマフォを使用しますが、非常に短い時間ロックするつもりのスピンロックを使用します-特にたくさんロックする場合、ロックにはコストがかかります。このような場合、保護されたリソースがロック解除されるのを待つ間、少しの間スピンロックする方が効率的です。スピンが長すぎると、明らかにパフォーマンスに影響があります。

通常、スレッドクォンタムよりも長くスピンする場合は、セマフォを使用する必要があります。


27

Yoav Aviramとgbjbaanbが言ったことに加えて、他の重要なポイントは、セマフォはそのようなマシンでは理にかなっているのに対して、シングルCPUマシンでは決してスピンロックを使用しないということでした。最近では、複数のコア、ハイパースレッディング、または同等の機能を備えていないマシンを見つけるのに苦労することがよくありますが、CPUが1つしかない状況では、セマフォを使用する必要があります。(理由は明白だと思います。単一のCPUが他の何かがスピンロックを解放するのを待つのにビジーであるが、それが唯一のCPUで実行されている場合、現在のプロセスまたはスレッドがプリエンプトされるまで、ロックは解放されそうにありませんO / S。これには時間がかかる場合があり、プリエンプションが発生するまでは何も起こりません。)


7
次に、シングルスレッドシステムでスピンロックを使用しないことがいかに重要であるかを説明します。それらは、優先順位逆転問題にチェックされています。そして、私を信じてください。あなたはこの種のバグをデバッグしたくないのです。
Nils Pipenbrinck 08年

2
スピンロックは、1つ以上のCPUがあるかどうかに関係なく、Linuxカーネルではすべて終わっています。どういう意味?
ファルケン教授

@Amigable:定義により、スピンロックは、CPU上の現在のスレッドがロックされたオブジェクトを解放するために何か他のものを待っていることを意味します。ロックを変更できる唯一のアクティブなものが現在のCPUである場合、ロックはスピンしても解放されません。それ以外の場合-DMA転送または他のI / Oコントローラーがロックを解放できる場合は、すべて順調です。しかし、他に何もロックを解放できないときにスピンすることはあまり賢明ではありません。先取りされるのを待つため、今度は別のプロセスにCPUを譲ることもできます。
ジョナサンレフラー

1
私はかなり間違っているかもしれませんが、リエントラント(シングルCPU)Linuxカーネルが実行中のスピンロックを中断する可能性があるという印象を受けました。
Falken教授、

2
@Amigable:私も間違っている可能性がありますが、私はスピンロックの古典的な定義に近いと思います。プリエンプティブスケジューリングでは、プロセスはタイムスライスの終わりまで、または割り込みによってプロセスが停止するまでロックをスピンする可能性がありますが、別のプロセスがスピンロックのロックを可能にする条件を提供する必要がある場合、スピンロックはシングルCPUマシンでは良い考えです。私が取り組んでいるシステムにはスピンロックがあり、非ビジー待機モードに入る前のスピン数に構成可能な上限があります。これはユーザーレベルのスピンロックです。カーネルに違いがあるかもしれません。
ジョナサンレフラー

19

RubinniによるLinuxデバイスドライバーから

セマフォとは異なり、スピンロックは、割り込みハンドラなど、スリープできないコードで使用される場合があります


8

私はカーネルの専門家ではありませんが、ここにいくつかのポイントがあります:

カーネルのコンパイル中にカーネルプリエンプションが有効になっている場合、ユニプロセッサマシンでもスピンロックを使用できます。カーネルのプリエンプションが無効になっている場合、スピンロックは(おそらく)voidステートメントに拡張されます

また、セマフォとスピンロックを比較しようとしているとき、セマフォはIPC(ユーザーランド)に使用されているものではなく、カーネルで使用されているものを指していると思います。

基本的に、クリティカルセクションが小さく(スリープ/ウェイクアップのオーバーヘッドよりも小さい)、クリティカルセクションがスリープ可能なものを呼び出さない場合は、スピンロックが使用されます。クリティカルセクションが大きく、スリープできる場合は、セマフォを使用する必要があります。

ラマンシャロトラ。


7

スピンロックとは、マシンに依存するアセンブリ命令(テストアンドセットなど)を使用したスレッド間ロックの実装を指します。スレッドがループ(「スピン」)で単純に待機し、ロックが使用可能になるまで繰り返しビジー待機するため、これはスピンロックと呼ばれます。スピンロックは、短時間ロックするとパフォーマンスが向上するため、ミューテックス(オペレーティングシステム(CPUではなく)が提供する機能)の代わりに使用されます。

セマフォーは、IPCのオペレーティングシステムによって提供される機能です。そのため、その主な目的はプロセス間通信です。オペレーティングシステムによって提供される機能であるため、そのパフォーマンスは、(可能な場合でも)thead間ロック用のスピンロックのパフォーマンスほど良くありません。セマフォは、長期間のロックに適しています。

とはいえ、アセンブリにスプリンロックを実装するのは難しいため、移植性はありません。


4
すべてのマルチスレッドCPUにはスピンロック命令(「テストおよび設定」)が必要であり、保護されたリソースを「所有」していると複数のスレッドが判断する競合状態が常に発生するため、ハードウェアでは常に1つの命令として実装されます。
リチャードT

セマフォを理解しているかどうかわかりません...ダイクストラの発言をご覧ください:cs.cf.ac.uk/Dave/C/node26.html
gbjbaanb

POSIXは、スレッドが共有するセマフォと、プロセスが共有するセマフォを区別します。
グレッグロジャース

2
セマフォはプロセス間同期用であり、通信ではありません。
ヨハンベゼム

6

Linux固有ではなく、より一般的な私の見解を追加したいと思います。

メモリアーキテクチャとプロセッサの機能によっては、マルチコアまたはマルチプロセッサシステムにセマフォを実装するためにスピンロックが必要になる場合があります。そのようなシステムでは、2つ以上のスレッド/プロセスが必要なときに競合状態が発生する可能性があるためです。セマフォを取得します。

はい。メモリアーキテクチャが1つのコア/プロセッサによるメモリセクションのロックを提供し、他のすべてのアクセスを遅らせる場合、およびプロセッサがテストと設定を提供する場合は、スピンロックなしでセマフォを実装できます(ただし、慎重に! )。

ただし、シンプル/安価なマルチコアシステムが設計されているため(私は組み込みシステムで作業しています)、すべてのメモリアーキテクチャがこのようなマルチコア/マルチプロセッサ機能をサポートしているわけではなく、テストと設定または同等の機能しかサポートしていません。次に、実装は次のようになります。

  • スピンロックを獲得する(ビジー待機)
  • セマフォを取得しようとする
  • スピンロックを解除します
  • セマフォが正常に取得されなかった場合は、セマフォが解放されるまで現在のスレッドを一時停止します。それ以外の場合は、クリティカルセクションに進みます

セマフォを解放するには、次のように実装する必要があります。

  • スピンロックを取得する
  • セマフォを解放する
  • スピンロックを解除します

はい、OSレベルの単純なバイナリセマフォの場合、スピンロックのみを代わりに使用することが可能です。ただし、保護するコードセクションが非常に小さい場合のみです。

前述のように、独自のOSを実装する場合は、注意が必要です。そのようなエラーのデバッグは楽しいですが(私の意見では、多くの人が共有しているわけではありません)、ほとんどの場合非常に退屈で困難です。


1

「ミューテックス」(または「相互排他ロック」)は、2つ以上の非同期プロセスが共有リソースを排他的に使用するために予約できる信号です。「mutex」の所有権を取得する最初のプロセスは、共有リソースの所有権も取得します。他のプロセスは、最初のプロセスが "mutex"の所有権を解放するのを待ってから、それを取得しようとします。

カーネルで最も一般的なロックプリミティブは、スピンロックです。スピンロックは非常にシンプルなシングルホルダーロックです。プロセスがスピンロックを取得しようとして利用できない場合、プロセスはロックを取得できるまで試行(スピン)を続けます。この単純さにより、小さくて速いロックが作成されます。


1

スピンロックが使用されるのは、スレッドの実行スライス時間の期限が切れる前に、予想される結果がすぐに発生することが確実である場合だけです。

例:デバイスドライバーモジュールで、ドライバーはハードウェアレジスタR0に「0」を書き込み、そのR0レジスタが1になるのを待つ必要があります。H/ WはR0を読み取り、いくつかの作業を行い、R0に「1」を書き込みます。これは一般的に高速です(マイクロ秒単位)。回転は、スリープ状態になってH / Wによって中断されるよりもはるかに優れています。もちろん、回転中は、ハードウェア障害状態に注意する必要があります。

ユーザーアプリケーションがスピンする理由はまったくありません。それは意味がありません。いくつかのイベントが発生するようにスピンし、そのイベントは別のユーザーレベルのアプリケーションで完了する必要があります。このアプリケーションは、迅速な時間枠内で発生することが保証されていません。したがって、ユーザーモードではまったくスピンしません。ユーザーモードでは、sleep()またはmutexlock()またはセマフォlock()を使用する方が適切です。


1

以下からのスピンロックとセマフォの違いは何ですか?マチェイPiechotka

どちらも限られたリソースを管理します。まず、バイナリセマフォ(ミューテックス)とスピンロックの違いについて説明します。

スピンロックはビジー待機を実行します。つまり、ループを実行し続けます。

while(try_acquire_resource()); 
 ...  
release();

これは非常に軽量なロック/ロック解除を実行しますが、同じリソースにアクセスしようとする他のスレッドがロックスレッドをプリエンプトする場合、2番目のスレッドはCPUクォンタムがなくなるまでリソースを無理にしようとします。
一方、mutexは次のように動作します。

if(!try_lock()){
    add_to_waiting_queue();
    待つ();
}
...
プロセス* p = get_next_process_from_waiting_queue();
p-> wakeUp();

したがって、スレッドがブロックされたリソースを取得しようとすると、そのスレッドが使用可能になるまで中断されます。ロック/ロック解除ははるかに重いですが、待機は「自由」で「公正」です。

セマフォは、複数回(初期化から既知)の使用が許可されているロックです。たとえば、3つのスレッドが同時にリソースを保持することは許可されますが、それ以上は許可されません。たとえば、プロデューサー/コンシューマーの問題、または一般的にキューで使用されます。

P(resources_sem)
resource = resources.pop()
...
resources.push(resources)
V(resources_sem)

セマフォ、ミューテックス、スピンロックの違いは?

Linuxでのロック


1
これのコピー/貼り付けのようです;-):スピンロックとセマフォの違いは何ですか?
Hibou57 2013

0

スピンロックを保持できるのは1つのプロセスだけですが、セマフォは1つ以上のプロセスで保持できます。スピンロックは、プロセスがロックを解放してからロックを取得するまで待機します。セマフォはロックをスリープ状態にしています。つまり、待機してスリープ状態になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.