スレッド競合とは何ですか?


120

誰かがスレッド競合とは何かを簡単に説明できますか?

私はそれをグーグルで調べました、しかし簡単な説明を見つけることができないようです。


9
そのため、漠然とした考えを書いてください。そうすれば、どこに行っているのか、または理解が正しいのかを確認できます。
James Black、

回答:


87

基本的にスレッドの競合とは、あるスレッドが別のスレッドによって現在保持されているロック/オブジェクトを待機している状態です。したがって、この待機中のスレッドは、他のスレッドがその特定のオブジェクトのロックを解除するまで、そのオブジェクトを使用できません。


53
この回答は不完全です(他のほとんどの回答と同様)。ロックは競合が発生する可能性のあるタイプの1つですが、そのようなものだけとはほど遠いものです。ロックレスリソースの競合も発生する可能性があります。(たとえば、2つのスレッドがアトミックに同じ整数をインクリメントし続ける場合、それらはキャッシュのピンポンにより競合が発生する可能性があります。ロックは関係しません。)
David Schwartz

スレッドが常にGILを取得する必要があるCPythonなどのグローバルインタープリターロック(GIL)の場合、同じプロセスで実行されている複数のスレッドがデフォルトで競合します。
Acumenus 2013

デッドロックに関して説明したと思いますが、デッドロックとは大きく異なります。
Harshit Gupta

185

いくつかの回答はロックの競合に焦点を当てているようですが、競合が発生する可能性があるのはロックだけではありません。競合とは、2つのスレッドが同じリソースまたは関連するリソースにアクセスしようとしたときに、競合するスレッドの少なくとも1つが他のスレッドが実行されていなかった場合よりも実行速度が遅くなることです。

競合の最も明白な例はロックです。スレッドAにロックがあり、スレッドBが同じロックを取得したい場合、スレッドBはスレッドAがロックを解放するまで待機する必要があります。

これはプラットフォーム固有ですが、他のスレッドがロックを解放するのを待つ必要がない場合でも、スレッドの速度が低下する可能性があります。これは、ロックによってある種のデータが保護され、データ自体も競合することが多いためです。

たとえば、ロックを取得し、オブジェクトを変更してから、ロックを解放して他のことを行うスレッドを考えてみます。2つのスレッドがこれを行っている場合、たとえロックを争うことがなくても、1つのスレッドしか実行していない場合よりも、スレッドの実行速度が大幅に遅くなる可能性があります。

どうして?各スレッドが最新のx86 CPU上の独自のコアで実行されており、コアがL2キャッシュを共有していないとします。スレッドが1つだけの場合、オブジェクトはほとんどの場合L2キャッシュに残る可能性があります。両方のスレッドが実行されている場合、一方のスレッドがオブジェクトを変更するたびに、もう一方のCPUがキャッシュラインを無効にしたため、もう一方のスレッドはL2キャッシュにデータがないことを検出します。たとえば、Pentium Dでは、これによりコードがL2キャッシュ速度よりもはるかに遅いFSB速度で実行されます。

ロック自体が競合しない場合でも競合が発生する可能性があるため、ロックがない場合にも競合が発生する可能性があります。たとえば、CPUが32ビット変数のアトミックインクリメントをサポートしているとします。1つのスレッドが変数をインクリメントおよびデクリメントし続けると、その変数は多くの場合、キャッシュ内でホットになります。2つのスレッドがそれを行うと、それらのキャッシュはその変数を保持するメモリの所有権をめぐって競合し、キャッシュコヒーレンシプロトコルがキャッシュラインの各コアの所有権を保護するように動作するため、多くのアクセスが遅くなります。

皮肉なことに、ロックは通常競合を減らします。どうして?ロックがないと、2つのスレッドが同じオブジェクトまたはコレクションを操作し、多くの競合を引き起こす可能性があるためです(たとえば、ロックのないキューがあります)。ロックは競合するスレッドのスケジュールを解除する傾向があり、競合しないスレッドを代わりに実行できます。スレッドAがロックを保持し、スレッドBが同じロックを必要とする場合、実装は代わりにスレッドCを実行できます。スレッドCがそのロックを必要としない場合は、しばらくの間、スレッドAとBの間の将来の競合を回避できます。(もちろん、これは実行可能な他のスレッドがあることを前提としています。システム全体が有益な進歩を遂げることができる唯一の方法が競合するスレッドを実行することである場合、それは役に立ちません。)


4
+1また、これを明示的にするために、2つのコアが争っている2つの変数は、競合を引き起こすために同じ変数である必要はなく、同じキャッシュラインのメモリに格納するだけで済みます。構造のパディングおよび/またはメモリへの構造の整列は、この形式の競合を回避するのに役立ちます。
Rob_before_edits

1
@Davidは、回答の最後のパラの詳細を理解するのに役立ちます
学習者

4
@Narojiそれについて質問してください。
David Schwartz

@ DavidSchwartz、Cプログラマですか?
Pacerier

@Pacerier C ++のほとんど。
David Schwartz、2015年

19

ここから:

競合は、スレッドがすぐに利用できないリソースを待っているときに発生します。コードの実行は遅くなりますが、時間の経過とともに解消される場合があります。

デッドロックは、スレッドが2番目のスレッドがロックしたリソースを待機していて、2番目のスレッドが最初のスレッドがロックしたリソースを待機しているときに発生します。3つ以上のスレッドがデッドロックに関与する可能性があります。デッドロックが解決することはありません。多くの場合、アプリケーション全体、またはデッドロックが発生している部分が停止します。


これは、スレッドコンテンションとデッドロックの違いについても説明しています
Sankalp

3

質問の背景にはOPからの説明があるはずだと思います-2つの回答が考えられます(このリストに追加があると確信しています)。

  1. スレッドの競合の一般的な「概念」と、それがアプリケーションでどのように表示されるかについて言及している場合は、上記の@DavidSchwartzの詳細な回答に従います。

  2. 「.NET CLRロックおよびスレッド:競合の総数」パフォーマンスカウンターもあります。このカウンターのPerfMonの説明から取ったように、次のように定義されます。

    このカウンターは、CLRのスレッドが管理されたロックの取得に失敗した合計回数を表示します。管理ロックはさまざまな方法で取得できます。C#の "lock"ステートメント、System.Monitor.Enterの呼び出し、またはMethodImplOptions.Synchronizedカスタム属性の使用。

...他のOSやアプリケーションフレームワークについては、他の人もきっと確信しています。


2

2つのスレッドがあります。スレッドAとスレッドBには、オブジェクトCもあります。

Aは現在オブジェクトCにアクセスしており、そのオブジェクトをロックしています。BはオブジェクトCにアクセスする必要がありますが、AがオブジェクトCのロックを解放するまでアクセスできません。


1

別の言葉は並行性かもしれません。それは単に、2つ以上のスレッドが同じリソースを使用しようとするという考えです。


1

私にとって競合は、共有リソースを介した2つ以上のスレッド間の競争です。リソースには、ロック、カウンターなどがあります。競合とは、「誰が最初に取得するか」を意味します。スレッドが多いほど、競合が多くなります。リソースへのアクセス頻度が高いほど、競合が多くなります。


1

次のシナリオを想像してみてください。あなたは明日の最終試験の準備をしていて、少しお腹が空いています。それで、あなたはあなたの弟に10ドルを与えて、あなたにピザを買うように彼に頼みます。この場合、あなたはメインスレッドであり、あなたの兄弟は子スレッドです。注文が与えられると、あなたと兄弟の両方が同時に仕事をします(つまり、ピザの勉強と購入)。ここで、考慮すべき2つのケースがあります。最初に、あなたの兄弟はあなたのピザを持ち帰り、あなたが勉強している間に終了します。この場合、勉強をやめてピザを楽しむことができます。第2に、ピザが利用可能になる前に、勉強を早く終えて、寝る(つまり、今日の割り当てられた仕事-明日の最終試験の勉強-が完了する)。もちろん、眠ることはできません。そうでなければ、ピザを食べる機会がありません。

例のように、2つのケースは競争の意味を与えます。


0

スレッドの競合は、I / O操作によっても影響を受けます。ファイルの読み取りを待機しているスレッドが競合と見なされる場合の例。ソリューションとしてI / O完了ポートを使用します。


0

ロックの競合は、スレッドが他のスレッドによってすでに取得されているオブジェクトへのロックを取得しようとしたときに発生します*。オブジェクトが解放されるまで、スレッドはブロックされます(つまり、スレッドは待機状態です)。場合によっては、これがいわゆるシリアル実行につながり、アプリケーションに悪影響を与えることがあります。

dotTraceドキュメントから

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.