目次
デッドロックってなに?
デッドロックとは、お互いがロック解除待ち状態となり、どちらも処理が進行できなくなる状態のことをいいます。
共有資源に対して複数のアクセスが同時に発生しても問題なく動作できるようにする制御を「排他制御」といい、排他制御には「ロック」や「ミューテックス」「セマフォ」などの方式があります。
排他制御により、共有資源をロックした際に発生する現象がデッドロックです。
資源に対してロックを掛ける場合、まずはじめに「資源」をロックします。ロックされた「資源」はロックが解除されるまで、他のタスク(処理)から操作することができなくなります。そのため上記図のように処理が終わったらロックを解除します。
スポンサーリンク
デッドロックの具体例
上記はデッドロックのイメージ図です。「タスクA」と「タスクB」はお互い「資源」のロックが解除されるのを待ち続けています。この状態がデッドロックです。
前提条件
共有の「資源A」と「資源B」を使って「タスクA」と「タスクB」の処理を実行する
- タスクAの処理は:「資源A」を更新してから「資源B」を更新し、処理をコミットする。
- タスクBの処理は:「資源B」を更新してから「資源A」を更新し、処理をコミットする。
※どちらのタスクも「資源A」「資源B」両方が正常に更新できた場合のみ正常終了とする。
[手順1] お互い共有資源をロックする
まずは共有資源のロックを取得します。これで「資源A」「資源B」はロックが解除されるまで他のタスクで操作できなくなります。
- タスクA:「資源A」のロックを取得
- タスクB:「資源B」のロックを取得
[手順2] お互い資源を更新する
次にお互い資源を更新する処理を行います。
- タスクA:「資源A」のデータを更新
- タスクB:「資源B」のデータを更新
[手順3] 資源Bのロックが解除されるまで待機
タスクAは次に「資源B」のロックを取得します。しかし「資源B」はタスクBにロックされているので、「資源B」のロックが解除されるまで待機します。
[手順4] 資源Aのロックが解除されるまで待機
タスクBは次に「資源A」のロックを取得します。しかし「資源A」はタスクAにロックされているので、「資源A」のロックが解除されるまで待機します。
結果「タスクA」と「タスクB」はどちらも待機状態となり、身動きが取れなくなってしまいました。
ポイント
デッドロックを回避するには、以下のような対応が一般的です。
- 資源のロック順序を両方のタスクで揃える
- 不必要にロックを掛けない
- 可能な限り行ロックを採用する(資源全体ではなく、更新対象の行のみロック)