理系学生日記

おまえはいつまで学生気分なのか

問題3-39 (3.4.1 The Nature of Time in Concurrent Systems)

make-serializer で生成されるオブジェクトは,関数を引数に取って,直列化された関数を返すシリアライザ.直列化された関数は,その実行時にインタリーブされない.そのために,

(define x 10)

(define s (make-serializer))

(parallel-execute (s (lambda () (set! x (* x x))))
                  (s (lambda () (set! x (+ x 1)))))

上の一連の関数を実行すると,最終的な x の値は

(lambda () (set! x (* x x)))

が先に実行された場合の 101 か,

(s (lambda () (set! x (+ x 1))))

が先に実行された場合の 121 のどちらかに制限される.


じゃぁ,下記を実行した後の最終的な x の値はどうなり得るのか.

(define x 10)

(define s (make-serializer))

(parallel-execute (lambda () (set! x ((s (lambda () (* x x))))))
                  (s (lambda () (set! x (+ x 1)))))

まず,101 と 121 は最終的な x の値としてあり得るのは自明.今回は

(lambda () (set! x ((s (lambda () (* x x))))))

上記関数において,x^2 の計算と x への代入との間にインタリーブされる可能性がある.実際にそのとき何が起こるのかを考えることにする.parallel-execute の第一引数に渡されている関数を p1,第二引数となっている関数を p2 とすると,

  1. x が 100 (初期状態)
  2. p1 が x^2=100 を計算する
  3. p2 が x に 11 を代入する (インタリーブ)
  4. p1 が x に 100 を代入する.

というわけで,x が 100 になる可能性がある.

以上から,x が取る値としては,100,121,101 がある.