マルチコアと同期
上のコードは、CAS(&p, 期待値, 新しい値)を使って共有の変数counterを2倍にしている。CASが失敗してループをやり直すのはどのようなときか。
int old, new;
do {
old = counter;
new = old * 2;
} while (!CAS(&counter, old, new));
- Acounterの値が0のとき
- Boldを読んでからCASを実行するまでの間に、ほかのスレッドがcounterを書き換えたとき
- Cnewの値がoldより大きいとき
答えと解説を見る
正解:B. oldを読んでからCASを実行するまでの間に、ほかのスレッドがcounterを書き換えたとき
CASは、counterが読んだときのoldのままなら新しい値を書き込みます。その間にほかのスレッドが値を変えていると、手元のnewは古い値をもとに計算したものなので書き込まず、失敗を返します。ループは最新の値を読み直して計算をやり直します。足し算だけならフェッチ・アンド・アッドで済みますが、2倍にするような任意の更新もこの形で不可分に行えます。
- A. 0でも、ほかから変えられていなければ成功します。
- B. 正しい。古い値をもとにした計算を捨ててやり直します。
- C. 値の大小は失敗の条件ではありません。