Как блокировки реализованы на нескольких ядрах
Для однопроцессорной системы алгоритм блокировки довольно прост.
Lock(threadID) {
Disable Interrupts
If lock is already owned by same thread{
Restore Interrupts
return
}
if lock is free {
make lock busy
set current thread as the owner of the lock
}
else {
add threadID to the lock queue.
}
Restore Interrupts
return
}
Но как мы реализуем этот код в многопроцессорных / многоядерных системах. Что делать, если 2 ядра / прокси пытаются заблокировать разные процессы?
2 ответа
Мьютексы обычно реализуются с атомарными операциями над одним значением памяти. Например, блокировка может быть одним словом, которое свободно, когда 0
и заблокирован, когда 1
, Чтобы получить блокировку, процессор заблокирует шину памяти (чтобы другие процессоры не могли читать или записывать в память), считывать самое актуальное значение слова и устанавливать его 1
если это 0
и разблокировать шину памяти. Чтобы разблокировать, слово может быть установлено в 0
,
Это простой пример, который не обращается к тому, что происходит, когда утверждается блокировка. Разные ОС справляются с этим, используя разные механизмы. Linux использует что-то под названием futexes. Я не уверен, что делают Windows или Mac.
Несмотря на то, что вы выложили правильный алгоритм, код, не являющийся ядром, не может отключить прерывания процессора, поэтому код пользовательского пространства будет стремиться использовать атомарные операции даже на одном ядре.
Я говорю, что самый простой способ думать о блокировке - это инструкция атомного обмена. Следующее приобретает блокировку X.
ЗАМОК: установить RegisterA = 1 Atomic_Exchange(X, RegisterA) // работает так, что никакой другой поток не может работать с X если RegisterA == 1: Означает, что Х был 1, когда я преследовал обмен, таким образом, у кого-то еще есть замок Поскольку у меня нет блокировки, перейдите к LOCK еще: Если A равно нулю, это означает, что я был первым, кто установил X в 1, что означает, что я владею замком Разблокировка: X = 0
Атомный обмен существует в большинстве компьютеров. Intel x86 имеет инструкцию EXCHG для этого. Только к вашему сведению, Intel x86 также имеет инструкцию сравнения и обмена, которая позаботится о приобретении, а также о сравнении для вас. По сути, вместо того, чтобы сначала выполнять обмен, а затем выполнять тестирование в программном обеспечении, он использует аппаратное обеспечение и выполняет обмен только в том случае, если X==0 для начала. Это экономит дополнительную запись в переменную X, что уменьшает количество кеш-ошибок для X, что приводит к повышению производительности.