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

Заключение

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

Функции, обслуживающие мьютексы, можно разбить на следующие группы:

  • инициализация и разрушение мьютексов: pthread_mutex_init(), pthread_mutex_destroy() ;
  • захват и освобождение мьютексов: pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_timedlock(), pthread_mutex_unlock() ;
  • опрос и установка атрибутов мьютекса:
    pthread_mutex_getprioceiling(), pthread_mutex_setprioceiling();
  • инициализация и разрушение атрибутных объектов мьютексов:
    pthread_mutexattr_init(), pthread_mutexattr_destroy();
  • опрос и установка атрибутов мьютекса в атрибутных объектах:
    pthread_mutexattr_gettype(), pthread_mutexattr_settype(),
    pthread_mutexattr_getpshared(), pthread_mutexattr_setpshared(),
    pthread_mutexattr_getprotocol(), pthread_mutexattr_setprotocol(),
    pthread_mutexattr_getprioceiling(),
    pthread_mutexattr_setprioceiling();

Для инициализации статически описанных мьютексов с подразумеваемыми значениями атрибутов целесообразно пользоваться макросом PTHREAD_MUTEX_INITIALIZER.

У инициализированного мьютекса имеется четыре атрибута:

  • тип (обслуживается функциями pthread_mutexattr_gettype() и pthread_mutexattr_settype()) ;
  • верхняя грань приоритетов выполнения (функции pthread_mutex_getprioceiling(), pthread_mutex_setprioceiling(), pthread_mutexattr_getprioceiling(), pthread_mutexattr_setprioceiling());
  • протокол ( pthread_mutexattr_getprotocol(), pthread_mutexattr_setprotocol()) ;
  • признак использования несколькими процессами ( pthread_mutexattr_getpshared(), pthread_mutexattr_setpshared() ).

В стандарте POSIX-2001 определены четыре типа мьютексов:

PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_ERRORCHECK,
PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_DEFAULT.

Атрибут "протокол" влияет на планирование потока управления во время владения мьютексом. Согласно стандарту, возможных протоколов три: PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, PTHREAD_PRIO_PROTECT.

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

while (! предикат) {
   Ожидание на переменной условия с освобождением мьютекса.
   После успешного завершения ожидания поток вновь
      оказывается владельцем мьютекса.
}

После нормального выхода из цикла проверяемое условие истинно; можно выполнить требуемые действия и освободить мьютекс.

Разблокирование потоков управления, ожидающих на переменной условия, должен обеспечить другой поток, изменивший значения разделяемых переменных и отправивший ждущим соответствующее уведомление.

Функции, предлагаемые стандартом POSIX-2001 для обслуживания переменных условия, можно разделить на следующие группы:

  • инициализация и разрушение переменных условия:
    pthread_cond_init(), pthread_cond_destroy();
  • блокирование ( ожидание ) на переменной условия:
    pthread_cond_wait(), pthread_cond_timedwait();
  • разблокирование (прекращение ожидания) потоков управления, блокированных на переменной условия: pthread_cond_broadcast(), pthread_cond_signal() ;
  • инициализация и разрушение атрибутных объектов переменных условия: pthread_condattr_init(), pthread_condattr_destroy() ;
  • опрос и установки атрибутов переменных условия в атрибутных объектах: признака использования несколькими процессами (обслуживается функциями pthread_condattr_getpshared(), pthread_condattr_setpshared() ) и идентификатора часов реального времени, используемых для ограничения ожидания на переменной условия (функции pthread_condattr_getclock(), pthread_condattr_setclock().

Блокировки чтение-записьинтеллектуальное средство синхронизации, отличающее читателей от писателей. В большинстве случаев разделяемые данные чаще читают, чем изменяют, и это делает блокировки чтение-запись весьма употребительными.

Применительно к блокировкам чтение-запись предоставляются следующие группы функций:

  • инициализация и разрушение блокировок:
    pthread_rwlock_init(), pthread_rwlock_destroy();
  • установка блокировки на чтение: pthread_rwlock_rdlock(), pthread_rwlock_tryrdlock(), pthread_rwlock_timedrdlock() ;
  • установка блокировки на запись: pthread_rwlock_wrlock(), pthread_rwlock_trywrlock(), pthread_rwlock_timedwrlock() ;
  • снятие блокировки чтение-запись: pthread_rwlock_unlock() ;
  • инициализация и разрушение атрибутных объектов блокировок:
    pthread_rwlockattr_init(), pthread_rwlockattr_destroy();
  • опрос и установки атрибутов блокировок в атрибутных объектах:
    pthread_rwlockattr_getpshared(), pthread_rwlockattr_setpshared().

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

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

  • инициализация и разрушение спин-блокировок:
    pthread_spin_init(), pthread_spin_destroy();
  • установка спин-блокировки: pthread_spin_lock(), pthread_spin_trylock() ;
  • снятие спин-блокировки: pthread_spin_unlock().

Барьеры – своеобразное средство синхронизации, идея которого заключается в том, чтобы в определенной точке ожидания собралось заданное число потоков управления. Только после этого они смогут продолжить выполнение.

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

Функции, ассоциированные с барьерами, подразделяются на следующие группы:

  • инициализация и разрушение барьеров: pthread_barrier_init(), pthread_barrier_destroy() ;
  • синхронизация на барьере: pthread_barrier_wait() ;
  • инициализация и разрушение атрибутных объектов барьеров:
    pthread_barrierattr_init(), pthread_barrierattr_destroy();
  • опрос и установки атрибутов барьеров в атрибутных объектах:
    pthread_barrierattr_getpshared(),
    pthread_barrierattr_setpshared().
    Когда к функции pthread_barrier_wait() обратилось требуемое число потоков управления, одному из них (стандарт POSIX-2001 не специфицирует, какому именно) в качестве результата возвращается именованная константа PTHREAD_BARRIER_SERIAL_THREAD, а всем другим достаются нули. После этого барьер возвращается в начальное (инициализированное) состояние, а выделенный поток может выполнить соответствующие объединительные действия.