Spinlock
Материал из Википедии — свободной энциклопедии
Для улучшения этой статьи желательно?:
|
Спинлок (англ. Spinlock) — низкоуровневый примитив синхронизации, применяемый в многопроцессорных системах для реализации взаимного исключения.
Физически спинлок представляет собой переменную в памяти и реализуется на атомарных операциях, которые должны присутствовать в системе команд процессора. Каждый процессор, желающий получить доступ к разделяемому ресурсу, атомарно записывает условное значение «занято» в эту переменную, используя аналог операции swap (в архитектуре x86 — xchg). Если предыдущее значение переменной (возвращаемое командой) было «свободно» то считается, что данный процессор получил доступ к ресурсу, в противном случае, процессор возвращается к операции swap и крутится в цикле ожидая, пока спинлок будет освобождён. После работы с разделяемым ресурсом процессор-владелец спинлока должен записать в него условное значение «свободно».
Пример реализации спинлока на ассемблере x86:
mov eax, spinlock_address mov ebx, SPINLOCK_BUSY wait_cycle: lock xchg [eax], ebx cmp ebx, SPINLOCK_FREE jnz wait_cycle ;<спинлок захвачен данным процессором, работа с разделяемым ресурсом> mov eax, spinlock_address mov ebx, SPINLOCK_FREE lock xchg [eax], ebx
Более интеллектуальная реализация будет использовать обычную, а не атомарную операцию, для опроса в цикле, а атомарную операцию — только для попыток захвата. Дело в том, что реализация атомарных операций с памятью происходит путем аппаратного блокирования системной шины процессором на время выполнения атомарной операции (которая включает чтение, модификацию и запись). В течении выполнения этих трёх операций выполнение каких-либо других операций на шине невозможно, это снижает производительность других процессоров в системе (если они разделяют общую шину), даже если они не имеют никакого отношения к данному спинлоку.
Также используются т. н. queued spinlocks — «спинлоки с очередью». В них вместо присвоения 0 или 1 в атомарную переменную используется атомарное добавление структуры на голову списка, при том, что голова списка есть атомарная переменная типа «указатель».
Полезные свойства queued spinlockов:
- гарантия порядка предоставления в порядке запроса, гарантия от «голоданий»
- в цикле опроса каждый процессор опрашивает свою локальную переменную
- ровно 1 атомарная операция при захвате и ровно 1 при освобождении
Как правило, спинлоки применяются только в системном программном обеспечении для синхронизации более высокоуровневых примитивов, например таких как Мьютекс. Реализация примитивов синхронизации и диспетчера потоков обязательно требует блокировок, защищающих списки нитей, готовых к исполнению, и списки нитей, ожидающих на объектах. Такая блокировка может быть только спинлоком ввиду её очень низкого уровня. Таким образом, спинлок есть низший примитив синхронизации, на котором основана реализация всех остальных.
В пользовательских приложениях, работающий под управлением многозадачных ОС, использование спинлоков недопустимо, так как ожидание освобождения спинлока приводит к активному ожиданию в цикле, впустую расходующее вычислительные ресурсы процессора. Для синхронизации пользовательских программ должны применяться высокоуровневые примитивы, которые предполагают пассивное ожидание — если данная нить не может продолжить выполнение, то она отдаёт управление ОС, а не крутится в цикле ожидания спинлока (который потенциально может быть бесконечным).
Тем не менее спинлок с автоматическим наращиванием до захвата полноценного mutexа после истечения какого-то количества оборотов цикла применяется, например, в критических секциях Windows для оптимизации, заключающейся в отсутствии обращений к mutexу при отсутствии соревнования за ресурс.

