Вместо бинарного семафора, для которого так же используется функция sem_open, я рассмотрю гораздо чаще употребляемый семафор, называемый «мьютекс» (mutex).
Мьютекс по существу является тем же самым, чем является бинарный семафор (т.е. семафор с двумя состояниями: «занят» и «не занят»). Но термин «mutex» чаще используется чтобы описать схему, которая предохраняет два процесса от одновременного использования общих данных/переменных. В то время как термин «бинарный семафор» чаще употребляется для описания конструкции, которая ограничивает доступ к одному ресурсу. То есть бинарный семафор используют там, где один процесс «занимает» семафор, а другой его «освобождает». В то время как мьютекс освобождается тем же процессом/потоком, который занял его.
Без мьютекса не обойтись в написании, к примеру базы данных, к которой доступ могут иметь множество клиентов.
Для использования мьютекса необходимо вызвать функцию pthread_mutex_init():
#include <pthread.h> int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
Функция инициализирует мьютекс (перемнную mutex) аттрибутом mutexattr. Если mutexattr равен NULL, то мьютекс инициализируется значением по умолчанию. В случае успешного выполнения функции (код возрата 0), мьютекс считается инициализированным и «свободным».
Типичные ошибки, которые могут возникнуть:
· EAGAIN — недостаточно необходимых ресурсов (кроме памяти) для инициализации мьютекса
· ENOMEM — недостаточно памяти
· EPERM — нет прав для выполнения операции
· EBUSY — попытка инициализировать мьютекс, который уже был инициализирован, но не унечтожен
· EINVAL — значение mutexattr не валидно
Чтобы занять или освободить мьютекс, используем функции:
int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);
Функция pthread_mutex_lock(), если mutex еще не занят, то занимает его, становится его обладателем и сразу же выходит. Если мьютекс занят, то блокирует дальнейшее выполнение процесса и ждет освобождения мьютекса. Функция pthread_mutex_trylock() идентична по поведению функции pthread_mutex_lock(), с одним исключением — она не блокирует процесс, если mutex занят, а возвращает EBUSY код. Фунция pthread_mutex_unlock() освобождает занятый мьютекс.
Коды возврата для pthread_mutex_lock():
· EINVAL — mutex неправильно инициализирован
· EDEADLK — мьютекс уже занят текущим процессом
Коды возврата для pthread_mutex_trylock():
· EBUSY — мьютекс уже занят
· EINVAL — мьютекс неправильно инициализирован
Коды возврата для pthread_mutex_unlock():
· EINVAL — мьютекс неправильно инициализирован
· EPERM — вызывающий процесс не является обладателем мьютекса