スピンロックとセマフォ 質問する

スピンロックとセマフォ 質問する

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

スピンロックよりもセマフォを使用するのはどのような場合でしょうか?

ベストアンサー1

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

1. それが何であるか
スピンロックロックの実装方法の 1 つとして、ビジー ウェイティング ("スピニング") による実装が考えられます。セマフォはロックの一般化です (または逆に、ロックはセマフォの特殊なケースです)。通常、しかし必ずしもスピンロックは 1 つのプロセス内でのみ有効ですが、セマフォは異なるプロセス間の同期にも使用できます。

ロックは相互排他性のために機能する。つまり1つ一度に1つのスレッドだけがロックを取得し、コードの「クリティカルセクション」に進むことができます。通常、これは複数のスレッドで共有されるデータを変更するコードを意味します
セマフォカウンターを持ち、1つまたは複数スレッドは、投稿する値によって、また (一部の実装では) 最大許容値によって決まります。

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

2. 彼らが何をするのか
上で述べたように、スピンロックはロックであり、したがって相互排他 (厳密に 1 対 1) メカニズムです。これは、通常はアトミックな方法で、メモリ位置を繰り返し照会および/または変更することによって機能します。つまり、スピンロックの取得は「ビジー」な操作であり、CPU サイクルを長時間 (おそらく永久に!) 消費する可能性がありますが、実質的には「何も」達成しません。
このようなアプローチの主な動機は、コンテキスト スイッチには数百 (または数千) 回のスピンに相当するオーバーヘッドがあるため、数サイクルのスピン消費でロックを取得できる場合、全体的に非常に効率的である可能性があります。また、リアルタイム アプリケーションの場合、ブロックして、スケジューラが将来の遠い時間に戻ってくるのを待つことは受け入れられない可能性があります。

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

3. 混雑時にどのように行動するか
スピンロックやロックフリーアルゴリズムは「一般的に高速」である、または「非常に短いタスク」にのみ役立つ(理想的には、同期オブジェクトは絶対に必要な時間を超えて保持されるべきではない)という誤解がよくあります。
重要な違いは、異なるアプローチがどのように動作するかです。混雑がある場合

適切に設計されたシステムでは、通常、混雑は少ないか、まったくありません(つまり、すべてのスレッドが同時にロックを取得しようとしないということです)。たとえば、通常はないロックを取得し、ネットワークから0.5メガバイトのZIP圧縮データを読み込み、そのデータをデコードして解析し、最後に共有参照を変更(コンテナにデータを追加するなど)してからロックを解除するコードを書く。代わりに、ロックを取得するのは、データにアクセスするためだけに行う。共有リソースこれは、クリティカルセクションの外側の作業がクリティカルセクションの内側の作業よりかなり多いことを意味するため、当然、スレッドがクリティカルセクション内にいる可能性は比較的低く、同時にロックを争うスレッドは少ない。
もちろん、時々2つのスレッドが同時にロックを取得しようとすることがある(これができなかったそうなるとロックは不要になりますが、これは「健全な」システムでは規則というよりむしろ例外です。

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

一方、混雑が激しい場合や、ロックが長時間保持されている場合(時にはどうしようもないこともあります!)、スピンロックは何も達成せずに大量のCPUサイクルを消費します。
この場合、セマフォ(またはミューテックス)の方がはるかに良い選択です。これは、別のスレッドを実行できるようにするためです。役に立つその間、タスクを実行します。または、他のスレッドが何か有用な処理を行わない場合、オペレーティング システムは CPU を抑制して熱を減らし、エネルギーを節約します。

また、シングルコアシステムでは、スピンロックはロックの輻輳がある場合には非常に非効率になります。スピンしているスレッドは、解放スレッドがスケジュールされるまで、起こり得ない状態の変化を待つために時間を無駄にするからです。起こっていない待機中のスレッドが実行中の場合!したがって、どれでも競合の量によっては、ロックの取得には最良の場合でも約 1 1/2 のタイムスライスがかかります (解放スレッドが次にスケジュールされているスレッドであると想定)。これはあまり良い動作ではありません。

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

おすすめ記事