Что такое "спин-лок"?
Я всегда задавался вопросом, что они: каждый раз, когда я слышу о них, образы футуристических подобных маховику устройств танцуют (катятся?) В моей голове...
Кто они такие?
11 ответов
Когда вы используете обычные блокировки (мьютексы, критические секции и т. Д.), Операционная система переводит ваш поток в состояние WAIT и прерывает его, планируя другие потоки на том же ядре. Это снижает производительность, если время ожидания действительно мало, потому что ваш поток теперь должен ждать упреждения, чтобы снова получить время ЦП.
Кроме того, объекты ядра доступны не во всех состояниях ядра, например, в обработчике прерываний, когда подкачка недоступна и т. Д.
Спинлоки не вызывают прерывание, но ждут в цикле ("вращение"), пока другое ядро не снимет блокировку. Это предотвращает потерю кванта потоком и продолжается, как только блокировка будет снята. Простой механизм спин-блокировки позволяет ядру использовать его практически в любом состоянии.
Вот почему на одноядерном компьютере спин-блокировка - это просто "отключение прерываний" или "повышение IRQL", которое полностью предотвращает планирование потоков.
Спин-блокировки в конечном итоге позволяют ядрам избегать "больших блокировок ядра" (блокировка, полученная, когда ядро входит в ядро и освобождается при выходе), и имеет гранулярную блокировку примитивов ядра, вызывая лучшую многопроцессорную обработку на многоядерных машинах и, следовательно, более высокую производительность.
РЕДАКТИРОВАТЬ: возник вопрос: "Значит ли это, что я должен использовать спин-блокировки везде, где это возможно?" и я постараюсь ответить на него:
Как я уже упоминал, спин-блокировки полезны только в тех местах, где ожидаемое время ожидания короче кванта (читай: миллисекунды), и выгрузка не имеет особого смысла (например, объекты ядра недоступны).
Если время ожидания неизвестно или вы находитесь в пользовательском режиме, спин-блокировки не эффективны. Вы тратите 100% процессорного времени на ядро ожидания, проверяя, доступна ли спин-блокировка. Вы не позволяете другим потокам работать на этом ядре, пока не истечет ваш квант. Этот сценарий возможен только для коротких пакетов на уровне ядра и маловероятен для приложения в пользовательском режиме.
Вот вопрос на SO, касающийся этого: Спинлоки, насколько они полезны?
Скажем, ресурс защищен блокировкой, поток, который хочет получить доступ к ресурсу, должен сначала получить блокировку. Если блокировка недоступна, поток может неоднократно проверять, снята ли блокировка. В течение этого времени поток занят, ожидает, проверяет блокировку, использует процессор, но не выполняет никакой полезной работы. Такой замок называется спиновым замком.
Это довольно большой цикл, который продолжается до тех пор, пока не будет выполнено определенное условие:
while(cantGoOn) {};
Это тип блокировки, которая занята ожиданием
Это считается антишаблоном, за исключением программирования драйвера очень низкого уровня (когда может случиться, что вызов "правильной" функции ожидания требует больше затрат, чем просто занятая блокировка в течение нескольких циклов).
Смотрите, например, Spinlocks в ядре Linux.
SpinLocks - это те, в которых поток ожидает, пока блокировка не станет доступной. Обычно это используется, чтобы избежать накладных расходов на получение объектов ядра, когда есть возможность получения объекта ядра в течение небольшого периода времени.
Пример:
While(SpinCount-- && Kernel Object is not free)
{}
try acquiring Kernel object
Вы хотели бы использовать спин-блокировку, когда считаете, что дешевле войти в занятый цикл ожидания и объединить ресурс вместо блокировки, когда ресурс заблокирован.
Спиннинг может быть полезен, когда блокировки являются мелкозернистыми и имеют большое количество (например, блокировка на узел в связанном списке), а также когда время удержания блокировки всегда очень мало. В целом, удерживая спин-блокировку, следует избегать блокировки, вызывая все, что может блокировать само по себе, удерживая более одной спин-блокировки одновременно, совершая динамически отправляемые вызовы (интерфейс и виртуальные), делая статически отправляемые вызовы в любой код, который не выполняется. или владение памятью.
Также важно отметить, что SpinLock является типом значения по соображениям производительности. Таким образом, нужно быть очень осторожным, чтобы случайно не скопировать экземпляр SpinLock, поскольку эти два экземпляра (оригинал и копия) будут полностью независимы друг от друга, что, вероятно, приведет к ошибочному поведению приложения. Если необходимо передать экземпляр SpinLock, его следует передать по ссылке, а не по значению.
В двух словах, spinlock использует атомарное сравнение и обмен (CAS) или инструкции типа "тестируй и устанавливай" для реализации свободной от блокировки, ожидающей свободной от потоков идиомы. Такие структуры хорошо масштабируются в многоядерных машинах.
Что ж, да - смысл спиновых блокировок (против традиционных критических секций и т. Д.) Заключается в том, что они предлагают лучшую производительность при некоторых обстоятельствах (многоядерные системы...), потому что они не сразу дают остальную часть потока.
Спинлок - это тип блокировки, который не блокируется и не спит. Любой поток, который хочет получить спин-блокировку для любого общего или критического ресурса, будет непрерывно вращаться, тратя впустую цикл обработки ЦП, пока не получит блокировку для указанного ресурса. Получив спин-блокировку, он пытается завершить работу в своем кванте, а затем высвободить ресурс соответственно. Spinlock - это тип блокировки с наивысшим приоритетом, просто можно сказать, что это не приоритетный тип блокировки.
Это цикл, который вращается, пока не будет выполнено условие.