web-dev-qa-db-ja.com

ロックの競合状態を防ぐものは何ですか?

データ競合の基本と、ロック/ミューテックス/セマフォがそれらを防ぐのにどのように役立つかを理解しています。しかし、ロック自体に「競合状態」があるとどうなりますか?たとえば、おそらく同じアプリケーション内にあるが、異なるプロセッサ上で実行されている2つの異なるスレッドが、ロックを獲得しようとします完全に同時に

次に何が起こりますか?それを防ぐために何が行われますか?それは不可能ですか、それとも単にありそうもありませんか?それともrealの発生を待っている競合状態ですか?

24
Gavin Howard

それは不可能ですか、それとも単にありそうもありませんか?

不可能な。これは、たとえば Compare-and-swap などのさまざまな方法で実装でき、ハードウェアが順次実行を保証します。複数のコアまたは複数のソケットが存在する場合は少し複雑になる可能性があり、コア間に複雑な protocol が必要ですが、これはすべて処理されます。

36
maaartinus

アトミックな「テストと設定」操作の概念を研究します。

基本的に、操作を分割することはできません。2つの操作を同時に行うことはできません。値をチェックし、明確であれば設定し、テスト時の値を返します。ロック操作では、テストと設定の後、結果は常に "lock == TRUE"になります。唯一の違いは、開始時に設定されたかどうかです。

シングルコアプロセッサのマイクロコードレベルでは、これは分割不可能な1つの命令であり、実装は簡単です。マルチプロセッサとマルチコアプロセッサを使用すると、処理は難しくなりますが、シリコンを使用する非常に賢い人が作業するように設計されているため、プログラマーとして心配する必要はありません。基本的に彼らは同じことを行います-優れたバージョンのテストと設定を行うアトミックな命令を作成します

17
mattnz

コードをクリティカルセクションに配置するだけで、競合状態が相互排除に違反しないように特別に設計されています。

ほとんどの場合、ハードウェアレベルで実行されるアトミックな比較および設定ループが使用されます。

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
ratchet freak

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は無駄になりません)。これは常に真実であるとは限りません。スレッドが中断されている場合-コンテキストスイッチと呼ばれる負荷の高い操作が行われます。ただし、待機時間が短い場合(スレッド数〜コア数)は妥当です。

1
fex