pthread_mutexattr_t attr;
pthread_mutex_t mutex;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
Как подсказывает префикс "np" (not portable), исключающие семафоры рекурсивного и контролирующего типов специфичны для Linux и непереносимы в другие операционные системы. Поэтому не рекомендуется использовать их в программах широкого назначения.
4.4.4. Неблокирующие проверки исключающих семафоров
Иногда нужно, не заблокировав программу, проверить, захвачен ли исключающий семафор. Для потока не всегда приемлемо находиться в режиме пассивного ожидания, ведь за это время можно сделать много полезного! Функция pthread_mutex_lock()
не возвращает значения до тех пор, пока семафор не будет освобожден, поэтому она нам не подходит.
То, что нам нужно, — это функция pthread_mutex_trylock()
. Если она обнаруживает, что семафор свободен, то захватывает его так же, как и функция pthread_mutex_lock()
, возвращая при этом 0. Если же оказывается, что семафор уже захвачен другим потоком, функция pthread_mutex_trylock()
не блокирует программу, а немедленно завершается, возвращая код ошибки EBUSY
. "Права собственности" другого потока при этом не нарушаются. Можно попытаться захватить семафор позднее.
4.4.5. Обычные потоковые семафоры
В предыдущем примере, в котором группа потоков обрабатывает задания из очереди, потоковая функция запрашивает задания до тех пор, пока очередь не опустеет, после чего поток завершается. Эта схема работает в том случае, когда все задания помещаются в очередь заранее или новые задания поступают по крайней мере так же часто, как их запрашивают потоки. Но если потоки начнут работать слишком быстро, очередь опустеет и потоки завершатся. Может оказаться, что задание поступило, а потоков, готовых его обработать, уже нет. Следовательно, необходим механизм, который позволит блокировать потоки в случае, когда очередь пуста, а новые задания еще не поступили.
Такой механизм называется
Счетчик семафора является неотрицательным целым числом. Семафор поддерживает две базовые операции.
■ Операция
■ Операция
В Linux имеются две немного отличающиеся реализации семафоров. Та, которую мы опишем ниже, соответствует стандарту POSIX. Такие семафоры применяются для организации взаимодействия потоков. Другая реализация, служащая целям межпроцессного взаимодействия, рассмотрена в разделе 5.2, "Семафоры для процессов". При работе с семафорами необходимо включить в программу файл
.
Семафор представляется переменной типа sem_t
. Семафор следует предварительно инициализировать с помощью функции sem_init()
, передав ей указатель на переменную семафора. Второй параметр этой функции должен быть равен нулю,[14] а третий — это начальное значение счетчика семафора.
Чтобы выполнить операцию ожидания семафора, необходимо вызвать функцию sem_wait()
. Функция sem_post()
устанавливает семафор. Есть также функция sem_trywait()
, реализующая операцию неблокирующего ожидания. Она напоминает функцию pthread_mutex_trylock()
: если операция ожидания приведет к блокированию потока из-за того, что счетчик семафора равен нулю, функция немедленно завершается, возвращая код ошибки EAGAIN
.