race condition
概要
レースコンディションは 「並行処理(concurrency)」の文脈で語られる概念 です。
ただし
非同期処理(asynchronous) が関係する場面で「結果的に並行動作」していれば発生しうるし 並列処理(parallelism) は物理的に同時実行されるので、レースが発生しやすい環境です つまり、レースコンディションは「並行性を持つシステムで、共有状態を正しく同期できなかったときに生じる」現象です。
レースコンディションの怖さ
再現性が低い
タイミングに依存するため、テスト環境では再現しにくい
数ミリ秒の差で結果が変わる
一見正常に見える
競合が起きなければ正常動作するため、コードレビューで気づきにくい
レースコンディションを防ぐには
排他制御(Lock / Mutex)
同じリソースに同時アクセスしないように、ロック(Lock)を取る。
例:RedisのSETNXによる分散ロック、データベースのトランザクションロックなど。
更新時に「version番号」や「更新日時」をチェックし、
更新対象が自分の見ていたバージョンと一致している場合のみ反映。
RailsでもActiveRecordにlock_versionカラムを設けて同様の仕組みを持てます。
アトミック操作(Atomic Operation)
例えば「読み取り+更新」を1つの操作としてDBやKVS側で保証。
例:UPDATE ... SET count = count + 1 のように、読み書きを分けない。
同じ処理が何度呼ばれても結果が変わらないように設計。
例:DNS設定の「最新状態」を計算式から導くようにして、途中状態を残さない。
ステートマシン化と監査ログ
「どの状態からどの状態へ遷移できるか」を厳密に管理し、並列操作があっても許される遷移を限定する。
大規模分散システムでは、最終的整合性と状態遷移の一貫性が重要。