自作コンパイラの部屋 > 用語集 > クリティカルセクション
並行プログラミング(Concurrent Programming)では、並行して動くプログラム(プロセスやスレッド)が種々の資源(メモリ、ファイル、DB、周辺装置・・・)を共有することが多い。これら共有資源をプログラムが取り合う局面をクリティカルセクション(Critical Section)という。クリティカルセクションは並行プログラミングの最も難しい部分であり、バグが生まれる原因にもなりやすい。以下、具体例で説明しよう。
鈴木さんが山科信用金庫の口座からCDで5万円引き出すとしよう。CDのシステム側では、まず預金残高が5万円以上あるかどうかを調べ、okならば預金残高から5万円引くと共に、1万円札を5枚出すことになる。
上記を擬似的なプログラムで見てみよう。
1.~4.がクリティカルセクションである。この場合の共有資源はDB上の鈴木さんの預金残高である。これだけではピンと来にくいだろうから、次のシナリオを見てもらおう。
鈴木さんが佐藤さんと共謀して、同氏の預金をほぼ同時に引き出したとしよう。今鈴木さんの預金残高が6万円だったとすると、以下のようになる(可能性がある)。
鈴木 | 佐藤 | |||
処理 | 結果 | 処理 | 結果 | |
1 | X(メモリ) ← 預金(DB) | 6万円 | ||
2 | X(メモリ) ← 預金(DB) | 6万円 | ||
3 | IF X > 50000 THEN | OK | ||
4 | IF X > 50000 THEN | OK | ||
5 | X ← X - 50000 | 1万円 | ||
6 | X ← X - 50000 | 1万円 | ||
7 | 預金(DB) ← X | 1万円 | ||
8 | 預金(DB) ← X | 1万円 |
このシナリオから分かるように、6万円の預金から5万円を二回も引き出せた上に、残高が1万円残っている。つまり、5万円儲けたことになる。同じ手口で100万円でも1億でも儲けられることになる。
上記はたまたま顧客が儲かる結果になったが、これの裏返しで顧客が損をするシナリオも考えられる。同時に振り込みがあった場合がそうだ。
もちろん、信用第一の金融機関で、上記のような可能性がわずかでもあってはならない。ここで、読者の中には次のような疑問を持つ人がいるかもしれない。コンピュータのスピードを考えると、上記のようにタイミング良く処理が重なるなんてことは、たとえ意図的に試みても現実には起こり得ないのではないか、と。確かに、意図的に上記を起こすことは難しいが、偶然そうなってしまう可能性は十分にある。
ではどうすればよいかというと、①~④は並行実行してはいけない(それがクリティカルセクションということだが)、これらは一まとまりの処理として非並行的(逐次的)に実行しなければならない。
となると、クリティカルセクションを統一的に扱うための道具と方法論が欲しくなる。道具の基本となるのが「同期プリミティブ」であり、方法論は並行プログラミング理論である。同期プリミティブについては別稿にて説明する。
![]() |
目次 |