Что такое «спин-блокировки»?


108

Мне всегда было интересно, что это такое: каждый раз, когда я слышу о них, в моей голове танцуют (катятся?) Образы футуристических маховиков ...

Кто они такие?

Ответы:


125

Когда вы используете обычные блокировки (мьютексы, критические секции и т. Д.), Операционная система переводит ваш поток в состояние WAIT и вытесняет его, планируя другие потоки на том же ядре. Это приводит к снижению производительности, если время ожидания действительно короткое, потому что теперь ваш поток должен ждать прерывания, чтобы снова получить время ЦП.

Кроме того, объекты ядра доступны не во всех состояниях ядра, например, в обработчике прерываний или когда подкачка недоступна и т. Д.

Спин-блокировки не вызывают вытеснения, а ждут в цикле («вращении»), пока другое ядро ​​не освободит блокировку. Это предотвращает потерю кванта потока и продолжение его работы сразу после снятия блокировки. Простой механизм спин-блокировок позволяет ядру использовать его практически в любом состоянии.

Вот почему на одноядерной машине спин-блокировка - это просто «отключить прерывания» или «поднять IRQL», что полностью предотвращает планирование потоков.

В конечном итоге спин-блокировки позволяют ядрам избегать «больших блокировок ядра» (блокировка, полученная, когда ядро ​​входит в ядро ​​и освобождается при выходе), и имеют детализированную блокировку по примитивам ядра, что приводит к лучшей многопроцессорной обработке на многоядерных машинах и, следовательно, к повышению производительности.

РЕДАКТИРОВАТЬ : Возник вопрос: «Означает ли это, что я должен использовать спин-блокировки везде, где это возможно?» и я попробую на него ответить:

Как я уже упоминал, спин-блокировки полезны только в тех случаях, когда ожидаемое время ожидания короче кванта (читай: миллисекунды), а вытеснение не имеет особого смысла (например, объекты ядра недоступны).

Если время ожидания неизвестно, или если вы находитесь в пользовательском режиме, спин-блокировки неэффективны. Вы потребляете 100% процессорного времени на ожидающем ядре, проверяя, доступна ли спин-блокировка. Вы предотвращаете запуск других потоков на этом ядре до истечения срока действия вашего кванта. Этот сценарий возможен только для коротких пакетов на уровне ядра и маловероятен для приложения пользовательского режима.

Вот вопрос, касающийся этого: Spinlocks, насколько они полезны?


Означает ли это, что я должен использовать спин-блокировки (вместо мьютексов, критических разделов и т. д.) везде, где это возможно?

1
кто-нибудь, пожалуйста, поправьте меня, если я ошибаюсь, но спин-блокировка не отключает вытеснение (т.е. перепланирование). по той простой причине, что, если спин-блокировка ожидает ресурс, заблокированный другим процессом, то этому второму процессу должна быть предоставлена ​​возможность запустить и освободить ресурс. или для запуска второго процесса требуется вытеснение первого (вращения) процесса.
user1284631

вместо этого спин-блокировка не меняет состояние процесса с TASK_RUNNING на TASK_INTERRUPTIBLE (которое является спящим) и, таким образом, не сохраняет все об этом процессе (память, кеш и т. д.). вместо этого процесс вращения прерывается, но он никогда не завершает «немедленно планируемые» процессы: он сохраняется в памяти, а другие процессы регулярно запускаются до тех пор, пока один из них не освободит ресурс, который ожидает счетчик: в это время spinlock просто возвращается, и процесс вращения может продолжаться. он ожидает всегда в состоянии TASK_RUNNING.
user1284631

1
вы правы в этом (см. также это: linuxjournal.com/article/5833 ), но факт в том, что блокировка ресурсов и отключение прерываний, хотя и полезны для совместного выполнения, в остальном понятия не связаны. вы в основном хотите быть уверены, что не используете ресурс, обнаруженный в несогласованном состоянии, и именно поэтому вы проверяете его блокировку. отключение прерываний (также вытеснение) гарантирует, что да, никто не будет вмешиваться в ваше возрождение, пока вы с ним имеете дело. но для этого вы должны быть уверены, что ресурс свободен, когда вы его приобретаете.
user1284631

1
(затем отключите прерывания, чтобы убедиться, что никакая другая задача не вытесняет вас и не вмешивается в ресурс). на UP (однопроцессорном) это всегда так: самая первая (и последующие) спин-блокировка просто предоставляется, прерывания (т.е. вытеснение) отключаются, а задача, использующая ресурс, никогда не вытесняется: она выполняет все свои задание с ресурсом, затем разрешите прерывания (и, таким образом, вытеснение). когда вытеснение включено, то ресурс уже свободен. в основном, на UP нет конкуренции за спин-блокировку и нет ожидания . на SMP может быть.
user1284631

25

Скажем, ресурс защищен блокировкой, поток, которому требуется доступ к ресурсу, должен сначала получить блокировку. Если блокировка недоступна, поток может неоднократно проверять, была ли освобождена блокировка. В это время поток занят ждет, проверяя блокировку, используя ЦП, но не выполняя никакой полезной работы. Такая блокировка называется спин-блокировкой.


2
Хороший ответ! +1
Jayesh Bhoi 09

18

Это во многом цикл, который продолжается до тех пор, пока не будет выполнено определенное условие:

while(cantGoOn) {};

1
И / или while (cantGoOn) {sleep (0)};
Jiminion

@Jiminion, если вы поставите, sleep(0)он вытеснит поток, в первую очередь убив цель использования спин-блокировки. если вам нужно уступить место другим потокам, вы должны использовать обычную блокировку. (я знаю, что ваш комментарий очень старый, но хотел, чтобы другие не увидели в нем предложение).
Седат Капаноглу

«Нулевое значение заставляет поток передать оставшуюся часть своего временного отрезка любому другому потоку, который готов к запуску. Если нет других потоков, готовых к запуску, функция немедленно возвращается, и поток продолжает выполнение».
Jiminion


5

Это тип блокировки, который занят ожиданием

Это считается антипаттерном, за исключением программирования драйвера очень низкого уровня (где может случиться так, что вызов «правильной» функции ожидания имеет больше накладных расходов, чем простая блокировка занятости на несколько циклов).

См., Например, Spinlocks в ядре Linux .


3

SpinLocks - это те, в которых поток ожидает, пока блокировка не станет доступной. Обычно это используется, чтобы избежать накладных расходов на получение объектов ядра, когда существует возможность получения объекта ядра в течение некоторого небольшого периода времени.

Пример:

While(SpinCount-- && Kernel Object is not free)
{}

try acquiring Kernel object

3

Вы можете использовать спин-блокировку, если считаете, что дешевле войти в цикл ожидания и объединить ресурс в пул вместо блокировки, когда ресурс заблокирован.

Вращение может быть полезно, когда блокировки мелкие и имеют большое количество (например, блокировка на узел в связанном списке), а также когда время удержания блокировки всегда чрезвычайно короткое. В общем, удерживая спин-блокировку, следует избегать блокировки, вызова всего, что само может блокировать, одновременного удержания более одной спин-блокировки, выполнения динамически отправляемых вызовов (интерфейсных и виртуальных), выполнения статически отправляемых вызовов в любой код, который не используется. t владеть или выделять память.

Также важно отметить, что SpinLock является типом значения по соображениям производительности. Таким образом, нужно быть очень осторожным, чтобы случайно не скопировать экземпляр SpinLock, поскольку два экземпляра (оригинал и копия) будут полностью независимы друг от друга, что может привести к ошибочному поведению приложения. Если необходимо передать экземпляр SpinLock, его следует передавать по ссылке, а не по значению.


1

В двух словах, спин-блокировка использует атомарное сравнение и обмен (CAS) или инструкции типа test-and-set для реализации идиомы без блокировки и ожидания без блокировки потоков. Такие структуры хорошо масштабируются на многоядерных машинах.


По самому определению спин-блокировка не используется для реализации чего-либо, освобождающего от блокировки или освобождающего от ожидания.
rdb

0

Это цикл, который вращается до тех пор, пока не будет выполнено условие.


0

Что ж, да - смысл спин-блокировок (по сравнению с традиционными критическими секциями и т. Д.) В том, что они предлагают лучшую производительность при некоторых обстоятельствах (многоядерные системы ...), потому что они не сразу дают остальную часть кванта потока.


0

Spinlock - это тип блокировки, который не может блокировать и не спящий. Любой поток, который хочет получить спин-блокировку для любого общего или критического ресурса, будет непрерывно вращаться, тратя впустую цикл обработки ЦП, пока не получит блокировку для указанного ресурса. После получения спин-блокировки он пытается завершить работу в своем кванте, а затем соответственно высвобождает ресурс. Spinlock - это тип блокировки с наивысшим приоритетом, проще говоря, это не вытесняющая блокировка.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.