Я всегда задавался вопросом, каковы они: каждый раз, когда я слышу о них, изображения футуристических подобных маховику устройств идут, танцуя (прокрутка?) через мой ум...
Каковы они?
При использовании обычных блокировок (мьютексов, критических секций и т.д.) операционная система переводит свой поток в состояние WAIT и вытесняет его, планируя другие потоки на том же ядре, и вытесняет его. Это приводит к снижению производительности, если время ожидания действительно короткое, потому что ваш поток теперь вынужден ждать, когда предупреждение снова получит процессорное время.
Кроме того, объекты ядра доступны не во всех состояниях ядра, например, в обработчике прерываний, при недоступности подкачки и т.д.
Спин-блокировки не вызывают преемственности, а ждут в цикле ("spin"), пока другое ядро не освободит блокировку. Это предотвращает потерю потоком своего кванта и продолжается, как только блокировка освобождается. Простой механизм спин-блокировок позволяет ядру использовать его практически в любом состоянии.
Поэтому на одноядерной машине спинлок - это просто "отключить прерывание" или "поднять IRQL", что полностью исключает возможность планирования потока.
Блокировки ядра, в конечном счете, позволяют ядрам избегать "большой блокировки ядра" (блокировки, получаемой при входе ядра в ядро и освобождаемой при выходе) и имеют гранулярную блокировку по примитивам ядра, что приводит к лучшей многопроцессорности на многоядерных машинах и, таким образом, лучшей производительности.
EDIT: Возник вопрос: "Означает ли это, что я должен использовать spinlocks там, где это возможно?", и я попытаюсь ответить на него:
Как я уже упоминал, Spinlocks полезен только в тех местах, где ожидаемое время ожидания меньше кванта (читай: миллисекунды), а преемственность не имеет особого смысла (например, объекты ядра недоступны).
Если время ожидания неизвестно, или если вы находитесь в пользовательском режиме, Spinlocks не эффективны. Вы потребляете 100% процессорного времени на ожидающем ядре во время проверки наличия спинблока. Вы не позволяете другим потокам работать на этом ядре до тех пор, пока ваш квант не истечет. Этот сценарий возможен только при коротких всплестках на уровне ядра и вряд ли является вариантом для пользовательского приложения.
Вот вопрос в SO, адресующийся к этому: Спинблоки, насколько они полезны?
Допустим, ресурс защищен блокировкой, поток, который хочет получить доступ к ресурсу, должен сначала получить блокировку. Если блокировка недоступна, поток может многократно проверить, был ли он освобожден. В течение этого времени поток, занятый, ждет, проверяя блокировку, используя процессор, но не выполняя никакой полезной работы. Такая блокировка называется блокировкой вращения.
.SpinLocks - это те, в которых поток ждет, пока не станет доступен замок. Обычно это используется, чтобы избежать накладных расходов на получение объектов ядра, когда есть возможность получить объект ядра за небольшой промежуток времени.
Ex:
While(SpinCount-- && Kernel Object is not free)
{}
try acquiring Kernel object
while(something != TRUE ){};
// it happend
move_on();
Ну, да - суть спиновых замков (по сравнению с традиционными критическими секциями и т.д.) заключается в том, что при некоторых обстоятельствах (многоядерные системы...) они предлагают лучшую производительность, так как не сразу дают остальной квант потока.
Это цикл, который вращается до тех пор, пока не будет выполнено условие
.В двух словах spinLock использует атомные сравнения и подкачки (CAS) или инструкции типа "тест и набор" для реализации безопасной идиомы "свободный поток ждет свободного". Такие структуры хорошо масштабируются в многоядерных машинах.
Это пертентный цикл, который продолжается до выполнения определенного условия:
while(cantGoOn) {};
Это тип блокировки, который делает оживленным ждать
. Это считается анти-образцом, за исключением очень низкоуровневого программирования драйверов (где он может произойти, что вызывание «правильной» функции ожидания имеет больше накладных, чем Просто занят блокировкой для нескольких циклов).
См. Например Спинлокна в ядре Linux .