|
スピンロック(Spinlock)とは、ソフトウェア工学におけるロックの一種で、スレッドがロックを獲得できるまで単純にループ(スピン)して定期的にロックをチェックしながら待つ方式。スレッドはその間有益な仕事を何もせずに動作し続けるため、これは一種のビジーウェイト状態を発生させる。獲得されたスピンロックは明示的に解放するまでそのまま確保されるが、実装によってはスレッドがブロック(スリープ)したときに自動的に解放される場合もある。 スレッドが短時間だけブロックされるなら、スピンロックは効率的であり、オペレーティングシステムのプロセススケジューリングのオーバヘッドを防ぐことにもなる。このため、スピンロックはカーネル内でよく使われる。しかし、確保期間が長くなるとスピンロックは無駄が多くなり、他のスレッドの処理を妨害するだけでなく、再スケジューリングが必要になることもある。スレッドがロックを保持する時間が長くなればなるほど、ロックを持った状態でOSスケジューラによって割り込まれる可能性が高くなる。もしそうなると、ロックを保持しているスレッドがロックを解放することがないにも関わらず、他のスレッドはスピン(ロックを繰り返し獲得しようとする)し続けてしまう。その結果、ロックを保持するスレッドがロックを解放するまで、他のスレッドは先に進むことができない(indefinite postponement状態になる)。これはシングルプロセッサシステムには特に当てはまる。というのも、他のスレッドが並行して動く事は決してないので、いったんスピンし始めるとタイムスライスを使い切るまでスピンし続けることになるのである。 スピンロックを正しく実装することは難しい。なぜなら、競合状態を避けるためにロックの同時アクセスの可能性を考慮しなければならないからである。一般に、これは特別なアセンブリ言語の命令(アトミックなテスト・アンド・セット操作など)を使う必要があり、高級言語やアトミック命令をサポートしていない言語では簡単には実装できない。 アトミック命令をサポートしないアーキテクチャや、高級言語で実装しなければならない場合、ピーターソンのアルゴリズムといったアトミックでないロックアルゴリズムを用いることができるかもしれない。ただし、スピンロックより多くのメモリが必要になるかもしれないし、アウト・オブ・オーダー実行が許される場合は高級言語では実装できないかもしれない。 ==実装例== 以下の例は x86 アセンブリ言語によるスピンロックの実装である。Intel 80386互換プロセッサで動作する。 lock: # ロック変数。1 = ロック済み, 0 = ロックされていない dd 0 spin_lock: mov eax, 1 # EAX レジスタに 1 をセット loop: xchg eax, # アトミックにEAXレジスタとロック変数の値を交換 # ロックには常に 1 が格納され、以前の値が EAX レジスタに格納される。 test eax, eax # EAX 自身をチェック。EAX がゼロならば プロセッサのゼロフラグがセットされる。 # EAX が 0 なら、ロックは解放状態から新たに確保されたとみなせる。 # そうでなければ、EAX は 1 であり、ロックを獲得できていない。 jnz loop # ゼロフラグがセットされていないときは XCHG 命令に戻る。 # これはロックが既に他に獲得されていた場合で、スピンする必要がある。 ret # ロックを獲得できたので、呼び出した関数へ戻る。 spin_unlock: mov eax, 0 # EAX レジスタに 0 をセット xchg eax, # アトミックに EAX レジスタとロック変数を交換 ret # ロックを解放 抄文引用元・出典: フリー百科事典『 ウィキペディア(Wikipedia)』 ■ウィキペディアで「スピンロック」の詳細全文を読む 英語版ウィキペディアに対照対訳語「 Spinlock 」があります。 スポンサード リンク
|