マルチコアと同期

上のコードを2つのスレッドで同時に実行すると、counterの最終的な値が200000より小さくなることがある。その理由として正しいものはどれか。

int counter = 0;
// 2つのスレッドが同時に、それぞれ
for (int i = 0; i < 100000; i++)
    counter++;
  1. ACPUが加算の計算を間違えることがあるから
  2. Bcounter++は読み出し・加算・書き込みに分かれ、2つのスレッドの処理が重なると片方の加算が失われるから
  3. Cループの回数が、スレッドごとに自動で半分にされるから
答えと解説を見る

正解:B. counter++は読み出し・加算・書き込みに分かれ、2つのスレッドの処理が重なると片方の加算が失われるから

counter++は、メモリから値を読み、1を足し、メモリへ書き戻すという3つの操作です。スレッドAが100を読み、書き戻す前にスレッドBも100を読むと、どちらも101を書き込み、2回分の加算が1回分になってしまいます。これはデータ競合の典型例です。アトミックな加算命令を使うか、ロックで一度に1つのスレッドだけが更新するようにすれば、正しく200000になります。

  • A. CPUの計算は正しく行われています。
  • B. 正しい。同じ古い値に1を足して、同じ値を書き込んでしまいます。
  • C. ループの回数は変わりません。
この分野を解く 分野ページへ

マルチコアと同期のほかの問題

  1. アトミック命令(不可分命令)の説明として正しいものはどれか。
  2. アトミック命令CAS(コンペア・アンド・スワップ)の動作として正しいものはどれか。
  3. 上のコードは、CAS(&p, 期待値, 新しい値)を使って共有の変数counterを2倍にしている。CASが失敗してループをやり直すのはどのようなときか。
  4. RISC-VのLR/SC(ロード予約/条件付きストア)のような命令の組で、SC(条件付きストア)が失敗するのはどのようなときか。
  5. CASを使ったロックフリーのデータ構造で問題になるABA問題の説明として正しいものはどれか。