マルチコアと同期
上のコードを2つのスレッドで同時に実行すると、counterの最終的な値が200000より小さくなることがある。その理由として正しいものはどれか。
int counter = 0;
// 2つのスレッドが同時に、それぞれ
for (int i = 0; i < 100000; i++)
counter++;
- ACPUが加算の計算を間違えることがあるから
- Bcounter++は読み出し・加算・書き込みに分かれ、2つのスレッドの処理が重なると片方の加算が失われるから
- Cループの回数が、スレッドごとに自動で半分にされるから
答えと解説を見る
正解:B. counter++は読み出し・加算・書き込みに分かれ、2つのスレッドの処理が重なると片方の加算が失われるから
counter++は、メモリから値を読み、1を足し、メモリへ書き戻すという3つの操作です。スレッドAが100を読み、書き戻す前にスレッドBも100を読むと、どちらも101を書き込み、2回分の加算が1回分になってしまいます。これはデータ競合の典型例です。アトミックな加算命令を使うか、ロックで一度に1つのスレッドだけが更新するようにすれば、正しく200000になります。
- A. CPUの計算は正しく行われています。
- B. 正しい。同じ古い値に1を足して、同じ値を書き込んでしまいます。
- C. ループの回数は変わりません。