データ競合とは何か、そしてロック/ミューテックス/セマフォがそれらを防ぐのにどのように役立つのかを理解しています。しかし、ロック自体に「競合状態」がある場合はどうなりますか?たとえば、おそらく同じアプリケーション内にあるが、異なるプロセッサで実行されている2つの異なるスレッドが、まったく同時にロックを取得しようとします。
それではどうなりますか?それを防ぐために何が行われますか?それは不可能ですか、それともまったくありそうもないことですか?それとも、実際に発生するのを待っている競合状態ですか?
データ競合とは何か、そしてロック/ミューテックス/セマフォがそれらを防ぐのにどのように役立つのかを理解しています。しかし、ロック自体に「競合状態」がある場合はどうなりますか?たとえば、おそらく同じアプリケーション内にあるが、異なるプロセッサで実行されている2つの異なるスレッドが、まったく同時にロックを取得しようとします。
それではどうなりますか?それを防ぐために何が行われますか?それは不可能ですか、それともまったくありそうもないことですか?それとも、実際に発生するのを待っている競合状態ですか?
回答:
それは不可能ですか、それとも単なるありそうもないことですか?
不可能。さまざまな方法で実装できます。たとえば、ハードウェアが順次実行を保証するCompare-and-swapを介して実装できます。複数のコアまたは複数のソケットが存在する場合、少し複雑になる可能性があり、コア間に複雑なプロトコルが必要ですが、これはすべて処理されます。
アトミックな「テストと設定」操作の概念を研究します。
基本的に、操作を分割することはできません。2つのことをまったく同時に行うことはできません。値をチェックし、明確な場合は設定し、テスト時の値を返します。ロック操作では、テストと設定後の結果は常に「lock == TRUE」になります。唯一の違いは、開始時の設定かどうかです。
シングルコアプロセッサのマイクロコードレベルでは、これは分割できない1つの命令であり、簡単に実装できます。マルチコアプロセッサとマルチコアプロセッサを使用するのは難しくなりますが、プログラマーとして心配する必要はありません。シリコンを扱う本当に頭のいい人たちによって動作するように設計されています。本質的には同じことを行います-テストと設定の派手なバージョンであるアトミックな命令を作成します
競合セクションが相互排除に違反しないように、特別に設計されたクリティカルセクションにコードを配置するだけです。
ほとんどの場合、ハードウェアレベルで実行されるアトミックな比較および設定ループが使用されます。
while(!CompareAndSet(&lock, false, true));//busy loop won't continue until THIS thread has set the lock to true
//critical section
CompareAndSet(&lock, true, false);
それがなければ、相互排除を可能にするためのよく研究されたソフトウェアソリューションがあります。
2つ(またはそれ以上)のスレッドが同時にロックを取得することはできません。たとえば、いくつかのタイプの同期方法があります。
擬似コード:
1. while ( xchg(lock, 1) == 1); - entry protocole
XCHGは、最初に「ロック」変数に新しい値を設定してから古い値を返すアトミック操作(x86アーキテクチャ上に存在する)の例です。アトミックとは、割り込みできないことを意味します-上記の例では、新しい値を設定してから古い値を返すまでの間です。アトミック-何があっても決定的な結果。
2. Your code
3. lock = 0; - exit protocol
ロックが0に等しい場合、別のスレッドがクリティカルセクションに入り、ループが終了します。
アトミック操作が2つ.Wait()あり.Signal()、整数変数を呼び出すことができますint currentValue。
Wait():
if (currentValue > 0) currentValue -= 1;
else suspend current thread;
Signal():
If there exists thread suspended by semaphore wake up one of them
Else currentValue += 1;
クリティカルセクションの問題の解決は本当に簡単です。
擬似コード:
mySemaphore.Wait();
do some operations - critical section
mySemaphore.Signal();
通常、プログラミングスレッドAPIを使用すると、セマフォクリティカルセクションで最大同時スレッドを指定できます。明らかに、マルチスレッドシステムにはより多くの種類の同期(ミューテックス、モニター、バイナリセマフォなど)がありますが、それらは上記のアイデアに基づいています。スレッドのサスペンドを使用するメソッドは、アクティブな待機よりも優先されるべきであると主張することができます(CPUは無駄になりません)-常に真実とは限りません。スレッドが中断されている場合-コンテキストスイッチと呼ばれる高価な操作が実行されます。ただし、待機時間が短い場合(スレッドの数〜コアの数)が妥当です。