Мобильное программирование приложений реального времени в стандарте POSIX

       

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


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

  • инициализация и разрушение мьютексов: 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, а всем другим достаются нули.После этого барьер возвращается в начальное (инициализированное) состояние, а выделенный поток может выполнить соответствующие объединительные действия.



Содержание раздела