Сериализатор как граница перехода состояния
Ячейка блокировки и граница test-and-set не пускают второй вход, а сериализатор оборачивает изменяющие состояние процедуры.
Что необходимо защитить, чтобы обновление не могло прочитать состояние и завершиться уже после того, как другое обновление его изменило?
- Понимание того, что test-and-set! возвращает предыдущее состояние блокировки
- Разделение неудачи при захвате, освобождения блокировки и повторной попытки
- Оборачивание изменяющей состояние процедуры единой общей блокировкой
- Сравнение потери обновления из-за устаревшего чтения с сериализованным конечным расписанием
Блокировка представляет собой мутабельный список из одной ячейки. Процедура test-and-set! сообщает, содержала ли ячейка значение true, а в противном случае устанавливает в ячейку значение true и сообщает о предыдущем значении false. Поэтому первый захват проходит успешно, пересекающаяся попытка завершается неудачей, а повторная попытка после clear! завершается успешно. Эта браузерная программа моделирует атомарную границу реализации из SICP как одну именованную операцию в конечном расписании.
Процедура make-serializer принимает общую блокировку и возвращает обертку для процедуры. Эта обертка выполняет захват перед вызовом изменяющей состояние процедуры и сбрасывает блокировку после получения ее результата. В предоставленном конечном расписании сериализованная операция deposit завершается до того, как операция withdrawal прочитает баланс balance, поэтому оба обновления сохраняются в итоговом значении 90. Урок фиксирует именно это расписание и конечное состояние.
- Вывод
- —
- Значение
- —
- Диагностика
- —
Первая программа возвращает (#t #f #t #t). Вторая программа возвращает (80 110 90 90 #f).
В первом запуске найдите два перехода set-car!, разделенные операцией clear!, и определите пересекающийся вызов, который не выполняет мутации. Во втором запуске сравните два устаревших чтения внутри lost-update с сериализованной оберткой, которая захватывает блокировку, выполняет одно присваивание переменной balance, освобождает блокировку и только затем разрешает чтение следующей обертке. Трасса выполнения с фиксированным ограничением описывает только эти явные последовательные расписания.
Измените программу и сравните результат.
Установите общую блокировку в значение true непосредственно перед serialized-deposit. Предскажите результат и значение balance, затем очистите блокировку и вызовите deposit снова.
Показать подсказку
Занятая обертка не вызывает защищаемую процедуру. После операции clear! та же обертка может захватить блокировку и выполнить обновление.