Принципы работы операционной системы Silberschatz, Galvin и Gagne содержат следующее определение для команды 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);
Теперь, как достигается взаимное исключение, если нет условия для установки цели на ИСТИНА?
Рассмотрим следующую ситуацию: процесс P0 устанавливает блокировку разделяемой переменной в TRUE и входит в ее критический раздел. Другой процесс P1 вызывает TestAndSet() в цикле while выше, он возвращает TRUE (поскольку P0 имеет блокировку), но безостановочно устанавливает блокировку в FALSE. Второй раз, когда TestAndSet() вызывается в цикле while, он возвращает FALSE, а P1 переходит в критический раздел, хотя P0 находится в критическом разделе. Затем нарушается взаимное исключение.
Я несколько раз искал и наткнулся на статью Митхуна Ачарьи и Роберта Фундерика (из отдела CS Университета Северной Каролины), которая содержит следующее альтернативное определение TestAndSet():
boolean Test-and-Set(boolean target)
begin
if(target == false):
target = true;
return target;
end
Это имеет для меня гораздо больше смысла, я включил его для сравнения, а также потому, что в статье перечисляется книга Сильбершаца как одна из его ссылок.
Я просто не понимаю, как определение, которое я нашел в своем учебнике (тот, который я представил вначале), можно использовать для обеспечения взаимного исключения, может ли кто-нибудь помочь?