Опубликован: 06.12.2004 | Доступ: свободный | Студентов: 1179 / 142 | Оценка: 4.76 / 4.29 | Длительность: 20:58:00
ISBN: 978-5-9556-0021-5
Лекция 2:

Средства синхронизации потоков управления

Спин-блокировки

Спин-блокировки представляют собой чрезвычайно низкоуровневое средство синхронизации, предназначенное в первую очередь для применения в многопроцессорной конфигурации с разделяемой памятью. Они обычно реализуются как атомарно устанавливаемое булево значение (истина – блокировка установлена). Аппаратура поддерживает подобные блокировки командами вида "проверить и установить".

При попытке установить спин-блокировку, если она захвачена кем-то другим, как правило, применяется активное ожидание освобождения, с постоянным опросом в цикле состояния блокировки. Естественно, при этом занимается процессор, так что спин-блокировки следует устанавливать только на очень короткое время и их владелец не должен приостанавливать свое выполнение.

Для описываемых блокировок стандарт POSIX-2001 не предусматривает установки с ограниченным ожиданием. Это понятно, поскольку накладные расходы по времени на ограничение в типичном случае превысят само время ожидания.

По сравнению с мьютексами спин-блокировки могут иметь то преимущество, что ( активное ) ожидание и установка не связаны с переключением контекстов, активизацией планировщика и т.п. Если ожидание оказывается кратким, минимальными оказываются и накладные расходы. Приложение, чувствительное к подобным тонкостям, в каждой конкретной ситуации может выбрать наиболее эффективное средство синхронизации.

Согласно стандарту POSIX-2001, спин-блокировки обслуживаются следующими группами функций:

  • инициализация и разрушение спин-блокировок: pthread_spin_init(), pthread_spin_destroy() (см. листинг 2.32);
    #include <pthread.h>
    
    int pthread_spin_init (
      pthread_spinlock_t *lock, int pshared);
    
    int pthread_spin_destroy (
      pthread_spinlock_t *lock);
    Листинг 2.32. Описание функций инициализации и разрушения спин-блокировок.
  • установка спин-блокировки: pthread_spin_lock(), pthread_spin_trylock() (см. листинг 2.33);
    #include <pthread.h>
    
    int pthread_spin_lock (
      pthread_spinlock_t *lock);
    
    int pthread_spin_trylock (
      pthread_spinlock_t *lock);
    Листинг 2.33. Описание функций установки спин-блокировки.
  • снятие спин-блокировки: pthread_spin_unlock() (см. листинг 2.34).
    #include <pthread.h>
    int pthread_spin_unlock (
      pthread_spinlock_t *lock);
    Листинг 2.34. Описание функции снятия спин-блокировки.

Обратим внимание на то, что применительно к спин-блокировкам было решено не возиться с атрибутными объектами, а единственный поддерживаемый атрибутпризнак использования несколькими процессами – задавать при вызове функции pthread_spin_init().

Поскольку между применением мьютексов и спин-блокировок много общего, мы не будем приводить примеры программ, использующих спин-блокировки. Ограничимся маленьким, слегка модифицированным характерным фрагментом реализации функции sigsuspend() в библиотеке glibc (см. листинг 2.35).

pthread_spin_lock (&ss->lock);
/* Восстановим старую маску */
ss->blocked = oldmask;
/* Проверим ждущие сигналы */
pending = ss->pending & ~ss->blocked;
pthread_spin_unlock (&ss->lock);
Листинг 2.35. Фрагмент возможной реализации функции sigsuspend().

Спин-блокировка устанавливается на очень короткий участок кода; естественно, она должна быть реализована весьма эффективно, чтобы накладные расходы не оказались чрезмерными.