問題3-38〜42

「3.4 並列性:時が本質的」に入りました。この節で述べられているようなことをしっかりと理解しておかないと、再現困難なバグを生み出してしまうので、本書だけでなく、様々な文献に当たりながら知見を深め、それを日常のプログラミングに反映させていきたいと思っています。
問題3-38。三つのプロセスが混ざり合わさって処理されなければ、以下のような場合分けができます。

  • Peter->Paul->Mary ;=>45
  • Peter->Mary->Paul ;=>35
  • Paul->Peter->Mary ;=>45
  • Paul->Mary->Peter ;=>55
  • Mary->Peter->Paul ;=>40
  • Mary->Paul->Peter ;=>40

さらに、あるプロセスが値を計算している間に、他のプロセスがその値を変えてしまうといったようなケースが考えられます。Peterが100ドルの口座に10ドルを預け入れようとしている間に、Maryが口座金額の半分の払い出しが完了してしまい、その上で、Peterの預け入れプロセスによって10ドル足されると、110ドル。その後Paulが20ドルを払い出して口座の残りは90ドル。Maryの処理が口座金額に反映されていないような現象が発生してしまいます。
問題3-39。parallel-executeやserializerが登場します。この問題のケースでは、例えば、P1で(10*10)が実行された後は、serializeされていないので、P2が実行される可能性があり、この間にP2のプロセスが完了すると、その後に、P1のset!が実行され、P2の実行結果が反映されていない100という値が返ってくる場合もあるのではと考えられます。
問題3-40。serialize化されていないparallel-executeだと、以下のような値が返ってくる可能性があります。

  • 1000000 ;=>P1がxを100に設定し、次にP2がxを三乗する。
  • 1000000 ;=>P2がxを1000に設定し、次にP1がxを二乗する。
  • 1000 ;=>P2がxに(三回)アクセスし、P1がxを100に設定し、P2がxを設定する。
  • 100 ;=>P1がxに(二回)アクセスし、P2がxを1000に設定し、P1がxを設定する。
  • 10000 ;=>P1が(* x x)の評価でxの値に二度アクセスする間にP2がxを10から1000に変える。
  • 10000 ;=>P2が(* x x x)の評価でxの値にアクセスする間(二回目と三回目の間)にP1がxを10から100に変える。
  • 100000 ;=>P2が(* x x x)の評価でxの値にアクセスする間(一回目と二回目の間)にP1がxを10から100に変える。

sirialize化すれば、上から二つ以外の可能性が消えます。
問題3-41。銀行の口座を参照する手続きもsirialize化する必要があるかという問題ですが、この口座の仕組みの場合、口座の値を変える可能性があるのは、withdrawとdeposit手続きのみで、その手続き自体はsirialize化されていますから、別に、外部から口座を参照するだけならsirialize化する必要はないのではと思います。
問題3-42。make-sirializerの実装がどのようになっているのかわからないので何とも言えませんが、元の手続きをmake-sirializerで包んだ上で適用することに意味があるのなら、Benの実装だと、make-accountが定義された時にmake-sirializerが適用されてしまい、個々の呼び出し時には直列化されないのではないでしょうか。