Введение
В вычислительной технике, блокировка, которая заставляет поток непрерывно выполняться в цикле.
В разработке программного обеспечения спинлок – это блокировка, которая заставляет поток, пытающийся ее получить, просто ожидать в цикле ("крутиться"), многократно проверяя, свободна ли блокировка. Поскольку поток остается активным, но не выполняет полезной работы, использование такой блокировки является разновидностью активного ожидания. После получения спинлоки обычно удерживаются до тех пор, пока не будут явно освобождены, хотя в некоторых реализациях они могут быть автоматически освобождены, если поток, на котором они ожидают (который удерживает блокировку), блокируется или "засыпает". Поскольку они избегают накладных расходов, связанных с перепланировкой процессов операционной системы или переключением контекста, спинлоки эффективны, если потоки, вероятно, будут заблокированы только на короткие периоды времени. По этой причине ядра операционных систем часто используют спинлоки. Однако спинлоки становятся неэффективными, если удерживаются в течение длительного времени, поскольку они могут препятствовать выполнению других потоков и требовать перепланировки. Чем дольше поток удерживает блокировку, тем выше риск того, что поток будет прерван планировщиком ОС во время удержания блокировки. Если это произойдет, другие потоки будут продолжать "крутиться" (многократно пытаться получить блокировку), в то время как поток, удерживающий блокировку, не будет продвигаться к ее освобождению. В результате происходит неопределенная отсрочка до тех пор, пока поток, удерживающий блокировку, не сможет завершить работу и освободить ее. Это особенно верно для однопроцессорной системы, где каждый ожидающий поток с одинаковым приоритетом, вероятно, потратит свое квантовое время (выделенное время, в течение которого поток может выполняться) на ожидание, пока поток, удерживающий блокировку, не завершит работу. Правильная реализация спинлоков является сложной задачей, поскольку программисты должны учитывать возможность одновременного доступа к блокировке, что может привести к гонкам данных. Как правило, такая реализация возможна только с помощью специальных инструкций языка ассемблера, таких как атомарные (т.е. не прерываемые) операции тестирования и установки, и не может быть легко реализована в языках программирования, не поддерживающих истинно атомарные операции. На архитектурах без таких операций или если требуется реализация на языке высокого уровня, может использоваться неатомарный алгоритм блокировки, например алгоритм Петерсона. Однако такая реализация может потребовать больше памяти, чем спинлок, быть медленнее в плане разрешения прогресса после разблокировки и может быть нереализуема на языке высокого уровня, если разрешено выполнение вне порядка.
Альтернативы
Основным недостатком спин-замка является то, что, ожидая получения замка, он тратит время, которое могло бы быть продуктивно использовано для других задач. Существует два способа избежать этого:
Не пытаться получить замок. Во многих ситуациях можно спроектировать структуры данных, не требующие блокировки, например, используя данные для каждого потока или для каждого процессора, а также отключая прерывания. Переключиться на другой поток во время ожидания. Обычно это включает в себя добавление текущего потока в очередь потоков, ожидающих получения замка, а затем переключение на другой поток, готовый к выполнению полезной работы. Эта схема также имеет преимущество в том, что она гарантирует отсутствие "голодания" ресурсов, при условии, что все потоки в конечном итоге освобождают полученные замки, и можно принимать решения о порядке выполнения потоков. Спин-замки, которые никогда не предполагают переключения, используемые в операционных системах реального времени, иногда называют "сырыми" спин-замками. Большинство операционных систем (включая Solaris, Mac OS X и FreeBSD) используют гибридный подход, называемый "адаптивным мьютексом". Идея заключается в использовании спин-замка при попытке доступа к ресурсу, заблокированному текущим потоком, но в переходе в состояние сна, если поток в данный момент не выполняется. (Последнее всегда верно для однопроцессорных систем.) OpenBSD предприняла попытку заменить спин-замки "ticket locks" (блокировками по принципу "первым пришел – первым обслужен"), однако это привело к увеличению загрузки процессора в ядре и значительному замедлению работы крупных приложений, таких как Firefox.