銀行口座オブジェクトを作成し、不変条件を維持したいとします。銀行口座の操作の結果として、お金が魔法のように作成または破棄されることはありません。
あなたは書くかもしれません
int balance;
void deposit(int amount) {
if (amount < 0) { throw ... }
long after = balance + amount;
if (after > Integer.MAX_VALUE) { throw ... }
// DANGER 1
balance = (int) after;
}
void withdraw(int amount) {
if (amount < 0 || amount > balance) { throw ... }
// DANGER 2
balance -= amount;
}
1つのスレッドが危険コメントのいずれかで一時停止し、同時に別の入金または出金が発生した場合に何が起こるかを考えてみてください。
ある預金が危険1で開始および一時停止し、次に別の預金が発生し、その後最初の預金が終了して価値が失われると、預金が失われる可能性があります。
1回の引き出しが開始され、危険2で一時停止し、その後預金が発生してから引き出しが終了した場合、引き出しによって残高がマイナスになる可能性があります。
入金が開始され、危険1で一時停止し、引き出しが行われ、入金が終了すると、お金が発生する可能性があります。
これを解決する標準的な方法は、値を計算してafter
割り当てるデポジットのコードbalance = (int) after
がクリティカルセクションであり、依存関係に介入する変更なしで発生する必要があると言うことですbalance
。
同様に、安全チェックインwithdrawal
と-=
操作はクリティカルセクションを形成します--=
チェックがまだ真でない場合、操作は発生しないはずです。
a -= b
ボーナスの楽しみのために、実際にはいくつかのステートメントが内部にあるため、何が起こるかを考えてください。
int x = b;
int y = a;
a = y - x;
意味のあるものにするためには、これらすべてが一緒に発生する必要があります。したがってa -= b
、標準的な意味を持つためには、その依存関係に依存し、操作の途中で変更されませんa
。b