Відповіді:
Коли ви використовуєте регулярні блокування (мутекси, критичні розділи тощо), операційна система переводить ваш потік у стан WAIT і попереджує його, плануючи інші потоки на тому ж ядрі. Це стягнення продуктивності, якщо час очікування дійсно короткий, тому що нитка повинна чекати, коли ви зможете знову отримати час процесора.
Крім того, об'єкти ядра недоступні в кожному стані ядра, наприклад, в оброблювачем переривань або коли підказка не доступна і т.д.
Спінлок не спричиняє перевагу, але чекайте в циклі ("віджимання"), поки інша ядро не звільнить замок. Це запобігає втраті потоком своєї кванти і продовжуватиметься, як тільки замок звільниться. Простий механізм відкрутки дозволяє ядру використовувати його практично в будь-якому стані.
Ось чому на одноядерній машині спінлок є просто "відключенням переривань" або "підвищенням IRQL", що запобігає плануванню потоків повністю.
Зрештою, Spinlocks дозволяють ядрам уникати "великого блокування ядра" (блокування, придбане, коли ядро потрапляє в ядро і вивільнене на виході) і мають детальне блокування над примітивом ядра, що сприяє кращій багатообробній обробці на багатоядерних машинах, тим самим кращі показники.
EDIT : Виникло запитання: "Чи означає це, що я повинен використовувати спілок, де це можливо?" і я спробую відповісти на це:
Як я вже згадував, Spinlocks корисні лише в тих місцях, де очікуваний час очікування коротший, ніж квантовий (читання: мілісекунди), і попередження не має особливого сенсу (наприклад, об’єкти ядра недоступні).
Якщо час очікування невідомий або ви перебуваєте в режимі користувача, Spinlocks не є ефективними. Ви споживаєте 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) або тестує і встановлює подібні інструкції для впровадження блокування, зачекайте вільну нитку безпечної ідіоми. Такі структури добре масштабуються в багатоядерних машинах.
Ну, так - суть замикання блокування (проти традиційних критичних розділів тощо) полягає в тому, що вони пропонують кращі показники роботи за певних обставин (багатоядерні системи ..), тому що вони не одразу дають решту кванту потоку.
Spinlock - це тип блокування, який не може блокувати і не спити. Будь-який потік, який хоче придбати спінлок для будь-якого спільного або критичного ресурсу, буде постійно крутитися, витрачаючи цикл обробки процесора до тих пір, поки він не придбає блокування для зазначеного ресурсу. Після придбання спінблоку він намагається завершити роботу в його кванті, а потім звільнити ресурс відповідно. Spinlock - найвищий пріоритетний тип блокування, просто можна сказати, це незаперечний вид блокування.