Книга «Принципы операционной системы» Зильбершатца, Галвина и Ганя содержит следующее определение инструкции TestAndSet() в главе о синхронизации:
boolean TestAndSet(boolean *target) {
boolean rv = *target;
*target = TRUE;
return rv;
}
Реализация взаимного исключения с помощью вышеуказанной инструкции также представлена следующим образом:
do {
while(TestAndSetLock(&lock))
; // do nothing
// critical section
lock = FALSE;
// remainder section
} while(TRUE);
Теперь, как достигается взаимное исключение, если нет условия для установки target в значение TRUE?
Рассмотрим следующую ситуацию: процесс P0 устанавливает для общей переменной lock значение TRUE и входит в свою критическую секцию. Другой процесс P1 вызывает TestAndSet() в цикле while выше, он возвращает TRUE (поскольку у P0 есть блокировка) и безоговорочно устанавливает для lock значение FALSE. Второй раз, когда TestAndSet() вызывается в цикле while, он возвращает FALSE, и P1 входит в свою критическую секцию, даже если P0 находится в своей критической секции. Тогда взаимное исключение нарушается.
Я немного поискал и наткнулся на статью Митхуна Ачарьи и Роберта Фундерлика (из отдела CS Университета штата Северная Каролина), которая содержит следующее альтернативное определение TestAndSet():
boolean Test-and-Set(boolean target)
begin
if(target == false):
target = true;
return target;
end
Это имеет для меня гораздо больше смысла, я включил его для сравнения, а также потому, что в документе книга Зильбершатца указана как одна из ссылок.
Я просто не понимаю, как определение, которое я нашел в своем учебнике (то, которое я дал первым), может быть использовано для достижения взаимного исключения, может ли кто-нибудь помочь?