serializer는 한 상태 전이가 끝난 뒤 다음 전이를 시작하게 한다.
잠금 셀과 test-and-set 경계는 겹친 진입을 거부하고 serializer는 공유 상태를 바꾸는 프로시저를 같은 잠금으로 감쌉니다.
한 갱신이 상태를 읽은 뒤 다른 갱신이 끝나고 나서야 쓰는 일을 막으려면 무엇을 보호해야 할까요?
- test-and-set!이 이전 잠금 상태를 반환한다고 읽기
- 획득 실패와 해제 뒤 재시도를 구분하기
- 공유 잠금 하나로 상태 변경 프로시저 감싸기
- 오래된 읽기의 갱신 손실과 직렬화된 유한 실행 비교하기
The lock is a one-cell mutable list. test-and-set! reports whether the cell was already true; otherwise it changes the cell to true and reports the previous false state. The first acquisition therefore succeeds, an overlapping attempt fails, and a retry after clear! succeeds. SICP treats test-and-set! as an atomic implementation boundary. This browser program models that boundary as one named operation; it does not create threads or establish machine-level atomicity.
make-serializer accepts a shared lock and returns a procedure wrapper. The wrapper acquires before calling the state-changing procedure and clears after receiving its result. In the shipped finite schedule, the serialized deposit finishes before the withdrawal reads balance, so both updates remain in the final value 90. The comparison program does not prove fairness, deadlock freedom, exception safety, or the outcome of every possible concurrent schedule.
(begin
(define (test-and-set! cell)
(if (car cell)
#t
(begin
(set-car! cell #t)
#f)))
(define (clear! cell) (set-car! cell #f))
(define lock (list #f))
(define first-acquire (not (test-and-set! lock)))
(define overlapping-acquire (not (test-and-set! lock)))
(clear! lock)
(define retry-acquire (not (test-and-set! lock)))
(list first-acquire
overlapping-acquire
retry-acquire
(car lock)))- 출력
- —
- 값
- —
- 진단
- —
The first program returns (#t #f #t #t). The second returns (80 110 90 90 #f).
In the first run, locate the two set-car! transitions separated by clear!, and distinguish the overlapping call that performs no mutation. In the second, compare the two stale reads inside lost-update with the serialized wrapper that acquires, completes one balance assignment, releases, and only then lets the next wrapper read. The bounded trace describes these explicit sequential schedules only.
힌트를 보기 전에 프로그램을 바꿔 보세요.
Set the shared lock to true immediately before serialized-deposit. Predict its result and balance, then clear the lock and call the deposit again.
힌트 하나 보기
A busy wrapper does not call its protected procedure. After clear!, the same wrapper can acquire and perform the update.