Я изучаю примеры блокировки/разблокировки, и у меня есть вопрос по Test&Set. Вот логика захвата и снятия блокировки с использованием функции Test&Set.
Думайте об этом как о ситуации, когда поток A имеет блокировку, а поток B хочет получить блокировку. Если поток A снимает блокировку (строка 2) после того, как поток B загружает переменную блокировки в регистр (строка 1), а поток B перезаписывает значение на 1 (строка 3), я думаю, что поток B сможет обойти бесконечный цикл в функции Acquire, поскольку нет возможности изменить переменную блокировки. Я прав?
// In Test&Set function
r = M[addr]; // thread B
M[addr] = 0; // thread A
M[addr] = 1; // thread B
Спасибо за Ваш ответ.
Я подумал, что если функция Test&Set является атомарной инструкцией, я не думаю, что такая ситуация произойдет, потому что никакая другая инструкция не вмешивается между двумя командами, но мне интересно, правильно ли это.
Тестирование и установка было бы бессмысленным, если не атомарным, по причинам, которые вы подозреваете.
@Community Пожалуйста, отключитесь. Вопрос совершенно ясен. Действительно это раздражает. Этого бота следует уничтожить.
Верно, в этом примере предполагается использование атомарной функции TestAndSet, а также использование атомарной функции записи в потоке A, если этого требует модель памяти языка. Такие функции будут использовать специальные аппаратные функции, чтобы гарантировать, что запись потока A не может происходить между чтением и записью в потоке B.
При использовании атомарных операций гарантированно произойдет одно из двух:
Либо запись в потоке A происходит до TestAndSet, и в этом случае TestAndSet устанавливает r в 0, а окончательное значение в M[addr]
равно 1. В этом случае поток B получает блокировку.
Или запись в потоке A происходит после TestAndSet, и в этом случае TestAndSet устанавливает r в 1. В этом случае поток B не получает блокировку, но запись в потоке A станет видимой через некоторое время, в результате чего M[addr]
будет иметь значение 0. Если TestAndSet повторяется после этой точки, он установит r в 0.
В любом случае, бесконечный цикл (тупик), который вас беспокоит, невозможен.
Чтобы этот алгоритм работал, функция
TestAndSet
должна быть атомарной. Современные ISA предоставляют инструкции, выполняющие атомарное тестирование и установку/сравнение и установку… или что-то подобное.