「空きを確認してから予約を確定する」——この2動作のすき間に別の人が割り込むと、両方とも「空き」を見て両方が確定し、二重予約や在庫マイナスが起きます。これが競合状態(レースコンディション)。防ぐには、確認と更新を途中で割り込まれない一続きにする=排他制御(ロック)が必要です。
先に押さえる
問題は「同時に複数の処理が同じデータを触る」こと。片方が読んで判断している間に、もう片方が同じ値を読んで別の判断をする。判断のもとになった値が、確定する頃には古くなっている——ここが事故の芯です。
競合状態が起きる瞬間
12人が同時に「残り1席」を見る
利用者A残り1席を確認
利用者B同時に残り1席を確認
2両方が「空いている」と信じて確定する
データ(残席)
↓Aが確定 → 残り0
↓Bも(古い「残り1」を根拠に)確定 → 二重予約
結果定員超過・在庫マイナス確認〜確定のすき間が原因
Bの確定は「確認した時点では正しかった」。でも確定の瞬間には状況が変わっていた。確認と確定が離れているほど、このすき間に割り込まれやすくなります。
防ぎ方 ― 確認と更新を一続きにする
見抜きどころ
直し方は「もっと速くする」ではなく、確認から更新までを他者が割り込めない一続きにすることです。対象の行にロックをかけて、片方が終わるまでもう片方を待たせる/更新時に「読んだ時と値が変わっていないか」を条件にして変わっていたらやり直す。設問では「いつ・どのデータの競合か」「なぜ確認だけでは足りないか(=確定まで守る)」を問われます。
つまずきやすい
「入力チェックを足す」だけでは防げません。チェックの後に割り込まれるからです。守るのはチェックそのものでなく、チェック〜確定の区間。また、ロックは必要な範囲・時間だけにしないと、今度は待ちが増えて処理が詰まります(かけ過ぎも設計ミス)。
起こり方と防ぎ方をひと目で
起こり方・リスク
- 確認と更新の間に割り込まれる(確認した時と確定する時で状態が変わる)
- 二重処理・在庫のマイナス・残高の不整合・二重購入などの実害
- 入力チェックを足すだけでは防げない(チェックの後で割り込まれる)
効く対策
- 確認〜確定を他者が割り込めない一続きに(対象の行にロック)
- 更新時に「読んだ時と値が変わっていないか」を条件にして、変わっていたらやり直す
- ロックは必要な範囲・時間だけ(かけ過ぎは待ち増加=性能劣化)