クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

競合状態とデッドロック

このレッスンのあとで: 競合状態とデッドロックが起きるわけを、説明することができる。

60分のレッスンコマンド4件毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

競合状態とは何か

競合状態(レースコンディション)とは、複数のプロセスやスレッドが同じデータを同時に書き換えて、結果が実行の順番しだいで変わる不具合です。商品の在庫数や口座の残高のような共有データで起きると、数が合わなくなります。

ネット通販で、在庫が10個の商品を、2人が同時に1個ずつ買いました。在庫は8になるはずです。ところが、9のままになることがあります。

このレッスンのゴール

メモ

競合状態とデッドロックが起きるわけを、説明することができる。

キーワード

ことばいみ
スレッド1つのプロセスの中で動く、1本の流れ
競合状態実行の順番しだいで、結果が変わる不具合
クリティカルセクション同時に1つだけが入るべき、共有データを触る部分
ロック1つだけが入れるように、入口にかける鍵
デッドロック互いに相手を待って、全員が動けなくなること
待ちグラフ誰が誰を待つかを矢印で表した図

学生が入力するセルは、このプレビューでは空白です。

読んで書く間に割り込まれると壊れる

「在庫を1つ減らす」は、実は3つの手順です。在庫を読み、1を引き、結果を書きます。2人の買い物が、この手順の途中で交互に入ると、片方の書き込みが消えます。

次の表は、最悪の交互の順番です。2人とも、書き込む前に10を読んでいます。

例: 2人が同時に買う

順誰がすること在庫
1A在庫を読む(10)10
2B在庫を読む(10)10
3A10から1を引いた9を書く9
4B10から1を引いた9を書く9

学生が入力するセルは、このプレビューでは空白です。

順番を手で並べて動かす

本物のスレッドは、順番が運しだいで変わります。そこで次のコマンドは、表と同じ順番を、手で並べて動かします。Aが読み、Bが読み、Aが書き、Bが書きます。

在庫は2回減らしたのに、結果は8ではなく9です。毎回、同じ答えが出ます。

更新が消える順番を再現する

コマンド
python3 -c "stock = 10; a = stock; b = stock; stock = a - 1; stock = b - 1; print(stock)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

スレッドはメモリを共有する

1つのプロセスの中には、スレッドという流れを、いくつも持てます。同じプロセスのスレッドは、メモリを共有します。だから速く協力できますが、同じデータを書き換え合う危険もあります。

次のコマンドは、ls というプロセスのスレッドの数を数えます。ls は1本だけで動くので、1と出ます。

スレッドの数を数える

コマンド
ls /proc/self/task | wc -l

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ロックで1つだけを通す

共有データを触る部分を、クリティカルセクションといいます。ここには、同時に1つしか入れません。入口にロックをかけて、持っているものだけが入れるようにします。

持っている間に、別のものが同じロックを取ろうとすると、待たされます。出るときに、ロックを返します。

例: ロックを使った2人の買い物

順誰がすること在庫
1Aロックを取る10
2Bロックを取ろうとして、待たされる10
3A読む、引く、書く(9)。ロックを返す9
4Bロックを取る。読む、引く、書く(8)8

学生が入力するセルは、このプレビューでは空白です。

flockでロックを試す

flock は、ファイルを使ったロックのコマンドです。-n を付けると、取れないときに待たず、すぐ終了コード1で失敗します。

最初のコマンドは、外側でロックを取り、その中で同じロックをもう一度取ろうとします。すでに持たれているので、断られて inner=1 と出ます。

持たれているロックは断られる

コマンド
flock -n /tmp/osint.lock -c 'flock -n /tmp/osint.lock true; echo inner=$?'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

誰も持っていなければ取れる

コマンド
flock -n /tmp/osint.lock true && echo free

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

デッドロックは互いに待ち続ける

デッドロックは、互いに相手が持つものを待って、全員が動けなくなることです。学生Aが会議室を借りてプロジェクターを待ち、学生Bがプロジェクターを借りて会議室を待つ場面です。

ロックでも同じことが起きます。次の4つがすべてそろったときに起きます。1つでも欠ければ、起きません。

デッドロックが起きる4つの条件

条件意味会議室の例
相互排他同時に使えるのは1人だけ会議室は1組だけ
保持と待機持ったまま、次を待つ会議室を持ってプロジェクターを待つ
横取りなし持つものを、無理に奪えない借りた部屋は返されるまで使えない
循環待ち待つ相手が輪になるAがBを待ち、BがAを待つ

学生が入力するセルは、このプレビューでは空白です。

よくある間違い

注意

「ロックを使えば、並行処理の問題はすべて消える」と考える人が多くいます。ロックが1つなら、競合状態は防げます。ただし、ロックが2つ以上あると、取る順序が食い違って、デッドロックになることがあります。

このラボとソースについて: 毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。