0

スレッドでこの小さな問題が発生しました。

    int x = 0;
    add() {

      x=x+1;
    }

これを複数のスレッド、たとえば4スレッドで実行すると、毎回x = 4の最終値になります。または、1、2、3、または4になる可能性があります。

ありがとう

PSは、追加の不可分操作は次のようになります。

LOAD A x
ADD A 1 
LOAD x A

その場合、最終結果は4になります。私は正しいのでしょうか、それとも何が間違っているのでしょうか。

4

3 に答える 3

3

これは、データ競合の典型的な例です。

それでは、add()の機能を詳しく見てみましょう。

add()
{
   x = x + 1;
}

これは次のように解釈されます。

  1. Xの最新の値を教えて、プライベートワークスペースに保存します
  2. プライベートワークスペースに保存されている値に1を追加します
  3. ワークスペースにあるものを、コピー元のメモリ(グローバルにアクセス可能)にコピーします。

これをさらに説明する前に、コンテキストスイッチと呼ばれるものがあります。これは、オペレーティングシステムがプロセッサの時間をさまざまなスレッドやプロセスに分割するプロセスです。このプロセスは通常、スレッドに有限のプロセッサ時間を与え(Windowsでは約40ミリ秒)、その作業を中断し、プロセッサがレジスタに持っているすべてのものをコピーして(したがって、その状態を保持して)、次のタスクに切り替えます。これは、ラウンドロビンタスクスケジューリングと呼ばれます。

処理が中断されて別のスレッドに転送されるタイミングを制御することはできません。

ここで、同じことを行う2つのスレッドがあると想像してください。

1. Give me the most recent value of X and store it in my private workspace
2. Add 1 to that value that is stored in my private workspace
3. Copy what I have in my workspace to the memory that I copied from (that is globally accessible).

そして、それらのいずれかが実行される前に、Xは1に等しくなります。

最初のスレッドは最初の命令を実行し、そのプライベートワークスペースに作業中の最新のXの値を格納する場合があります-1。次に、コンテキストスイッチが発生し、オペレーティングシステムがスレッドに割り込んで、キュー内の次のタスク、それはたまたま2番目のスレッドです。2番目のスレッドも1に等しいXの値を読み取ります。

スレッド番号2は、なんとか完了まで実行されます。「ダウンロード」した値に1を加算し、計算値を「アップロード」します。

オペレーティングシステムは、コンテキストスイッチを再度強制します。

これで、最初のスレッドは中断された時点で実行を継続します。それでも、最新の値は1であると見なされ、その値が1ずつインクリメントされ、計算結果がそのメモリ領域に保存されます。そして、これがデータの競合が発生する方法です。最終結果は3になると予想しますが、2です。

この問題を回避するには、ロック/ミューテックスコンペアアンドスワップアトミック操作など、さまざまな方法があります。

于 2012-07-05T13:03:55.980 に答える
2

あなたのコードは2つのレベルで壊れています:

  1. happens-beforeスレッドのアクション間には関係はありません。
  2. get-and-incrementのアトミシティは強制されません。

1.を解決するには、volatile修飾子を追加できます。これでも、操作は非アトミックのままになります。原子性を確保するには、(できれば)AtomicIntegerまたはsynchronized(ロックを含むが、好ましくない)を使用します。

現状では、インクリメントに関与しなかったスレッドから読み取られた場合、結果は0から4までの任意の数になる可能性があります。

于 2012-07-05T13:22:51.357 に答える
2

マルチスレッドアプリケーションは同時実行です(これが要点です)。

t1: LOAD A1 x
t2: LOAD A2 x
t3: LOAD A3 x
t4: LOAD A4 x
t1: ADD A1 1 
t2: ADD A2 1 
t3: ADD A3 1 
t4: ADD A4 1 
t1: STORE x A1
t2: STORE x A2
t3: STORE x A3
t4: STORE x A4

A1、A2、A3、A4はローカルレジスタです。

結果はですが、、または1になる可能性があります。別のスレッドがある場合は、可視性の問題のために古い値が表示され、2340

于 2012-07-05T13:23:33.470 に答える