serializer는 한 상태 전이가 끝난 뒤 다음 전이를 시작하게 한다.
잠금 셀과 test-and-set 경계는 겹친 진입을 거부하고 serializer는 공유 상태를 바꾸는 프로시저를 같은 잠금으로 감쌉니다.
한 갱신이 상태를 읽은 뒤 다른 갱신이 끝나고 나서야 쓰는 일을 막으려면 무엇을 보호해야 할까요?
- test-and-set!이 이전 잠금 상태를 반환한다고 읽기
- 획득 실패와 해제 뒤 재시도를 구분하기
- 공유 잠금 하나로 상태 변경 프로시저 감싸기
- 오래된 읽기의 갱신 손실과 직렬화된 유한 실행 비교하기
잠금은 단일 셀 변경 가능 리스트입니다. test-and-set!은 셀이 이미 참이었는지 보고하며, 그렇지 않다면 셀을 참으로 변경하고 이전의 거짓 상태를 보고합니다. 따라서 첫 번째 획득은 성공하고, 겹친 시도는 실패하며, clear! 이후의 재시도는 성공합니다. 이 브라우저 프로그램은 SICP의 원자적 구현 경계를 유한 스케줄의 이름 붙은 단일 연산으로 모델링합니다.
make-serializer는 공유 잠금을 받아 프로시저 래퍼를 반환합니다. 래퍼는 상태 변경 프로시저를 호출하기 전에 획득하고, 결과를 받은 뒤 해제합니다. 제공된 유한 스케줄에서는 출금이 balance를 읽기 전에 직렬화된 입금이 완료되므로, 최종값 90에 두 갱신이 모두 유지됩니다. 이 수업은 이 정확한 스케줄과 최종 상태를 기록합니다.
- 출력
- —
- 값
- —
- 진단
- —
첫 번째 프로그램은 (#t #f #t #t)를 반환합니다. 두 번째 프로그램은 (80 110 90 90 #f)를 반환합니다.
첫 번째 실행에서는 clear!로 구분되는 두 번의 set-car! 전이를 찾고, 아무런 변경도 수행하지 않는 겹친 호출을 구분하세요. 두 번째 실행에서는 lost-update 내부의 두 오래된 읽기를, 잠금을 획득하고 한 번의 balance 대입을 마친 뒤 해제하고 나서야 다음 래퍼가 읽도록 허용하는 직렬화된 래퍼와 비교해 보세요. 고정 제한 실행 흐름은 이러한 명시적인 순차 스케줄만을 설명합니다.
프로그램을 수정하고 결과를 비교해 보세요.
serialized-deposit 직전에 공유 잠금을 참으로 설정하세요. 그 결과와 balance를 예측한 다음, 잠금을 해제하고 입금을 다시 호출해 보세요.
힌트 보기
busy 상태의 래퍼는 보호 대상 프로시저를 호출하지 않습니다. clear! 이후에는 동일한 래퍼가 잠금을 획득하고 갱신을 수행할 수 있습니다.