問題3-43〜45

昨日の続きで、共有資源を複数のプロセスがアクセス・変更する際に発生する問題点について考察していきます。
問題3-43。二つの口座の残高差分を交換するexchangeですが、exchange手続き全体を直列化しないと、以下のような問題が発生する可能性があります。例えば、A=10ドル、B=20ドル、C=30ドルの残高があったとして、user1がAとBを、user2がAとCを交換しようとした時、

  • user1がBから差分10ドルを引き出す(B=10ドル)
  • user2がCから差分20ドルを引き出す(C=20ドル)
  • user1がAへ差分10ドルを預け入れる(A=20ドル)
  • user2がAへ差分20ドルを預け入れる(A=40ドル)

最終的な合計額は60ドルになり、それ以前の合計額と変わりませんが、exchangeが直列化されていれば、何回交換しても10ドル、20ドル、30ドルになるはずなので、上記の結果は異常な事態だということになります。
user1がAとCを、user2がBとCを交換しようとする場合は、さらに悪い事態が起こりそうです。残額が多い口座、少ない口座が予めわかっていた上で、exchangeの引数にその口座オブジェクトを渡す訳ですが、exchangeが直列化されていないと差分がマイナスになってしまい、正しく処理が行なえなくなってしまいます。
問題3-44。Benが書いた残額移動のロジックの場合、移動額は外部から与えられた値であり、この点が差分交換と大きく異なる点です。差分交換の場合、「差分を算出する -> 値をセットする(withdraw/deposit)」というプロセスがあり、この間に別のプロセスが入ることが差分交換ロジックの問題だったわけですが、残額移動の場合、このプロセスがありません。そのため、transfer手続きは直列化する必要はないのではと考えられます。
問題3-45。Louisが描いたmake-account-and-serializerですが、これを使ってserialized-exchangeを通すと、まず、口座オブジェクトであるaccount自体が直列化されますが、exchangeロジックの中でwithdrawやdepositを実行する際も直列化されています。ここに問題がありそうです。account自体はロックされているわけですから、withdraw/depositを使うことができず、そのためaccount自体も完了せず、処理が止まってしまうことになるのではないでしょうか?