並列環境ではおなじみの、排他制御に関する問題。共有リソースresの値を1インクリメントする際に、
- resの値を取得
- resの値を1インクリメント
- resの値をセット
という操作が行われますが、ここで1〜3の操作がアトミックではないため、途中でコンテキストスイッチが発生することがあります。そうすると期待したとおりに動作しないということになります。例えば、1の操作と3の操作の間に、別のスレッドによって1の操作が行われたとすると、それは「1インクリメントする前のresの値」を取得してしまいます。
この状態をわざと作るためにちょっと変更。
void func(void) { int i, tmp; for(i=0; i<5; i++){ tmp = res; usleep(1); res = tmp + 1; } }
10回実行してみました。
end: res=5 end: res=6 end: res=5 end: res=5 end: res=5 end: res=5 end: res=5 end: res=5 end: res=6 end: res=5 end: res=5
バラバラですね。