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