スピンロックとポーリングは同じことですか?
ウィキペディア:
スピンロックは、ロックを取得しようとしているスレッドが、ループが利用可能かどうかを繰り返し確認しながらループ(「スピン」)で単純に待機させるロックです。
これは次のように非常に聞こえます:
while(!ready);
それは完全に最適ではなかったので、可能な限りポーリングを回避するように教えられました。それで、スピンロックは悪い古い投票のための派手な名前ですか?スピンロックはポーリングとどう違うのですか?
ポーリングとは、リソース(任意リソースの種類)の準備ができているかどうかを繰り返し確認することを指します。
スピンロックは、ポーリングしているリソースがロックの場合です。
ポーリングはnotであることに注意してください。特に、通常、ポーリング時にデータの準備ができている場合、ポーリングは効率的です。ポーリングは、データを返さずに行う場合にのみ非効率的です。
一方、割り込みが頻繁に発生するほど多くのデータがある場合、割り込みは非効率的です。データがめったに到着せず、中断される前に実際に役立つ作業を実際に実行できる場合は、効率的です。
私自身の経験から実際の例を挙げましょう。15年前、新しい電子メールが届くたびに中断するように電子メールプログラムをセットアップしました。これは週に1〜2回行われました。常に受信トレイをチェックすることは、膨大な時間の無駄でした。
現在、すべての通知がオフになっています。私知っている私が自分の受信トレイを見るたびに、そこに新しいメールがあるでしょう。ポーリングは現在、はるかに効率的です。
スピンロックは、a)ロックが取得される可能性が低い場合、およびb)ifロックが取得される場合に効率的です。ロックは短時間しか保持されません。言い換えると、ほとんど競合されていない細粒度ロックに対しては効率的ですが、高度に競合されている粗粒度ロックに対しては非効率的です。
(そしてもちろん、スピンロックは真の並列処理が存在する場合にのみ機能します。そうでない場合、他のスレッドはロックを解放する機会がありません。それはある程度明白ですが、とにかくそれを述べたかったのです。)
スピンロックはロックの一種であり、具体的には、達成されたロックviaポーリングです。
ポーリングは、何かのステータスを確認する方法です(ステータスの通知を待つのではなく、ステータスを要求することにより)。
すべてのポーリングがスピンロックであるとは限りません。たとえば、キーボードのキーのステータスをポーリングします。
また、ポーリングは本質的に悪いことではありません。 非常にポーリングの期間が短いと、割り込みを使用する場合に必要となる高額なコンテキストシフトを回避できます。言うまでもなく、ポーリングは実装が簡単で、特に低レベルで維持しやすい場合があることは言うまでもありません。いつものように、絶対的なものはひどいものなので、オプションを盲目的に使用したり破棄したりするのではなく、ニーズに応じて適切なパフォーマンス/複雑さのトレードオフを提供する方法を使用する必要があります測定したとおり。
スピンロックはポーリングとは異なります。ポーリングは数ミリ秒以下の非常に短い期間でのみ発生するためです。ポーリングは無期限に続行できます。
並列プログラミングでは、スピンのbriefエピソードは、コンテキスト切り替えやカーネル遷移のコストを回避できるため、ブロックよりも望ましい場合がよくあります。
違いは、スピンロックは(うまくいけば)適切な状況でのみ使用され、これらの状況では非常に効率的であることです。
リソースが非常に短時間だけロックされることが予想される場合、たとえば、ロックが変数の更新にのみ使用される場合は、スピンロックを使用します。スピンロックは最高速度でロックをポーリングしますが、できればマイクロ秒未満です。通常のミューテックスでは、OS呼び出しが必要です。 [〜#〜] if [〜#〜]ロックが保持されるのはごくわずかな時間であり、スピンロックはごくわずかのCPU時間しか使用しませんが、OSの呼び出しには時間がかかります。しかし、この予想が間違っている場合、スピンロックは非常に非効率的です。1つのCPUで100%のCPU時間を使用しますが、通常のミューテックスはOSに入って戻るまでの時間しかかかりません。
両方が組み合わされることもあります。スピンロックを短時間実行し、スピンロックが機能しない場合は別の戦略に切り替えます。
過度のポーリングは、システムリソースを浪費するため、行うべきではありません。 システムリソースを浪費しない限り、ポーリングは問題ありませんになります。
たとえば、実際の作業で2%の負荷しか発生しない場合、過度のポーリングによりCPU負荷が100%になります。
ポーリングはwhile(!ready)
以外にも使用できます。たとえば、ユーザーがキーを押したかどうかを定期的にチェックすることを意味します。健全な実装では、最大15ミリ秒に1回チェックされるため、約2,000万クロックサイクルごとに1回チェックされます。このようなポーリングは、システムリソースを無駄にしないため、非常に便利です。
SpinLockはnotが特殊なケースです。 SpinLockがあり、1つのスレッドがロックに入り、別のスレッドが待機する必要がある場合、待機中のスレッドがシステムリソースを浪費する場合に限り、SpinLockは間違った選択です。待機中のスレッドは、ロックを取得する前にかなりの時間待機する必要がある場合にのみ、システムリソースを浪費します。
したがって、SpinLockを使用して再度ロック解除するまでに数千クロックサイクル以上必要なもの(たとえば、JavaScriptの一部を即座にコンパイルして実行するなど)を保護することは、まさにあなたが述べた理由により、悪いことです。ただし、適切に実装されたハッシュマップにアクセスするなど、SpinLockを使用してすばやく完了するものを保護すると、待機中のスレッドは2〜3回しかスピンせず、システムリソースを浪費しないため、問題ありません。