SICP問題3.48
口座に番号をつけて、プロセスはより小さい方の番号の方の口座を先に獲得しようとするデッドロック回避方法がうまくいく理由は以下のとおり。
番号の小さい方の口座から獲得するということは順番を固定化することであり、直列化しているということになる。
searialized-exchangeでデッドロックが発生する原因は各口座の獲得が並列で行われることにあり、その部分を直列化することによりデッドロックは回避できる。
上記の回避方法を取り入れた実装。
make-accountの修正
(define (make-account-and-serializer balance id) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (let ((balance-serializer (make-serializer))) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) ((eq? m 'balance) balance) ((eq? m 'serializer) balance-serializer) ((eq? m 'id) id) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch))
serialized-exchangeの修正
(define (exchange account1 account2) (let ((differnece (- (account1 'balance) (account2 'balance)))) ((account1 'withdraw) difference) ((account2 'deposit) difference))) (define (serialized-excahnge account1 account2) (let ((serializer1 (account1 'serializer)) (serializer2 (account2 'serializer))) (if (< (id account1) (id account)) ((serializer1 (serializer2 exchange)) account1 account2) ((serializer2 (serializer1 exchange)) account2 account1))))
しかし独自の識別番号つけるとこの実装を考えてないから、ちょっとアレですね。