Що саме таке «прядильні замки»?


108

Мені завжди було цікаво, що вони таке: щоразу, коли я чую про них, зображення футуристичних маховикових приладів танцюють (котяться?) Через мій погляд ...

Хто вони?

Відповіді:


125

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

Крім того, об'єкти ядра недоступні в кожному стані ядра, наприклад, в оброблювачем переривань або коли підказка не доступна і т.д.

Спінлок не спричиняє перевагу, але чекайте в циклі ("віджимання"), поки інша ядро ​​не звільнить замок. Це запобігає втраті потоком своєї кванти і продовжуватиметься, як тільки замок звільниться. Простий механізм відкрутки дозволяє ядру використовувати його практично в будь-якому стані.

Ось чому на одноядерній машині спінлок є просто "відключенням переривань" або "підвищенням IRQL", що запобігає плануванню потоків повністю.

Зрештою, Spinlocks дозволяють ядрам уникати "великого блокування ядра" (блокування, придбане, коли ядро ​​потрапляє в ядро ​​і вивільнене на виході) і мають детальне блокування над примітивом ядра, що сприяє кращій багатообробній обробці на багатоядерних машинах, тим самим кращі показники.

EDIT : Виникло запитання: "Чи означає це, що я повинен використовувати спілок, де це можливо?" і я спробую відповісти на це:

Як я вже згадував, Spinlocks корисні лише в тих місцях, де очікуваний час очікування коротший, ніж квантовий (читання: мілісекунди), і попередження не має особливого сенсу (наприклад, об’єкти ядра недоступні).

Якщо час очікування невідомий або ви перебуваєте в режимі користувача, Spinlocks не є ефективними. Ви споживаєте 100% часу процесора на сердечнику очікування, перевіряючи, чи доступний спінлок. Ви не дозволяєте іншим потокам запускатись на цьому ядрі до закінчення терміну дії вашого кванту. Цей сценарій можливий лише для коротких зривів на рівні ядра і навряд чи є варіантом для програми в режимі користувача.

Ось питання щодо ТА вирішення цього питання: Spinlocks, наскільки вони корисні?


чи означає це, що я повинен закручувати блокування (замість мютексу, критичного перерізу тощо), де це можливо?

1
хтось, будь ласка, виправте мене, якщо я помиляюся, але випуск блокування не вимикає попередження (тобто повторне планування). з простої причини, що якщо спінлок заблокує ресурс, заблокований іншим процесом, то цей другий процес повинен отримати шанс запуску та звільнення ресурсу. або, запуск другого процесу вимагає попереднього вилучення першого (прядіння) процесу.
користувач1284631

що замість цього відбувається, це те, що він не змінює стан процесу з TASK_RUNNING на TASK_INTERRUPTIBLE (який є сплячим станом) і, таким чином, він не економить усе про цей процес (пам'ять, кеш і так далі). натомість процес спінінгу випереджається, але він ніколи не закриває "негайно заплановані" процеси: він зберігається в пам'яті, а інші процеси регулярно запускаються, поки один із них не звільнить ресурс, який чекає спінер: у той час спінлок просто повертається, і процес прядіння може продовжуватися. він чекає в стані, що завжди TASK_RUNNING.
користувач1284631

1
Ви маєте рацію з цим (див. також це: linuxjournal.com/article/5833 ), але факт полягає в тому, що блокування ресурсу та відключення переривань, хоча це корисно виконувати спільно, є інакше не пов'язаними поняттями. ви в основному хочете бути впевнені, що ви не використовуєте ресурс, знайдений у непослідовному стані, і саме тому ви перевіряєте його блокування. вимкнення перерв (також попередження) гарантує, що так, ніхто не буде возитися з вашим воскресінням, поки ви маєте справу з ним. але для цього ви повинні бути впевнені, що ресурс вільний, коли ви його отримуєте.
користувач1284631

1
(тоді вимкніть переривання лише для того, щоб переконатися, що жодне інше завдання не дозволяє вам перешкоджати і возитися з ресурсом). У UP (uni-процесор) це завжди так: перший (і наступні) спінлок просто надається, переривання (тобто попередження) вимикаються, а завдання, що використовує ресурс, ніколи не передбачається: він робить все своє робота з ресурсом, а потім включити переривання (і, таким чином, попередження). коли ввімкнено попередження, то ресурс уже вільний. По суті, на UP немає ніяких спінальних розбіжностей і немає очікування . на SMP це може бути.
користувач1284631

25

Скажімо, ресурс захищений блокуванням, спочатку потрібна нитка, яка хоче отримати доступ до ресурсу. Якщо блокування недоступне, потік може кілька разів перевіряти, чи заблоковано блокування. Протягом цього часу зайнятий потік чекає, перевіряючи блокування, використовуючи процесор, але не виконуючи жодної корисної роботи. Такий замок називають спіновим замком.


2
Приємна відповідь! +1
Jayesh Bhoi

18

Це напевно багато циклу, який продовжує тривати, поки не буде виконано певну умову:

while(cantGoOn) {};

1
І / або поки (cantGoOn) {сон (0)};
Jiminion

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

"Значення нуля змушує потік відмовитись від залишку свого часового відрізка до будь-якого іншого потоку, який готовий запустити. Якщо немає інших потоків, готових до запуску, функція повертається негайно, і потік продовжує виконання."
Джимініон


5

Це тип замка, який зайнятий очікуванням

Це вважається антидіаграмою, за винятком дуже низького рівня програмування драйверів (де може статися, що виклик "правильної" функції очікування має більше накладних витрат, ніж просто зайняте блокування на кілька циклів).

Дивіться, наприклад, Spinlocks в ядрі Linux .


3

SpinLocks - це ті, у яких нитка дочекається появи блокування. Це, як правило, використовується, щоб уникнути накладних витрат об'єктів ядра, коли є можливість придбання об'єкта ядра протягом деякого невеликого періоду часу.

Наприклад:

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

try acquiring Kernel object

3

Ви б хотіли використовувати спінлок, коли вважаєте, що дешевше входити в зайнятий цикл очікування та об'єднати ресурс, а не блокувати, коли ресурс заблокований.

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

Також важливо відзначити, що SpinLock - це ціннісний тип, з міркувань продуктивності. Таким чином, потрібно бути дуже обережним, щоб випадково не скопіювати екземпляр SpinLock, оскільки два екземпляри (оригінал та копія) були б цілком незалежними один від одного, що, ймовірно, призведе до помилкової поведінки програми. Якщо екземпляр SpinLock повинен бути переданий навколо, він повинен передаватися за посиланням, а не за значенням.


1

Коротше кажучи, спінлок використовує атомне порівняння та заміну (CAS) або тестує і встановлює подібні інструкції для впровадження блокування, зачекайте вільну нитку безпечної ідіоми. Такі структури добре масштабуються в багатоядерних машинах.


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

0

Це цикл, який крутиться навколо, поки не буде виконано умову.


0

Ну, так - суть замикання блокування (проти традиційних критичних розділів тощо) полягає в тому, що вони пропонують кращі показники роботи за певних обставин (багатоядерні системи ..), тому що вони не одразу дають решту кванту потоку.


0

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.