Синхронизация потоков в ОС Linux, страница 2

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

Типичная последовательность для использования условной переменной:

·  Создание и инициализация условной переменной

·  Создание и инициализация ассоциированного мьютекса

·  Определение предиката (переменной, значение которой должно быть проверено)

·  Захват мьютекса

·  Исполнение потока доходит до точки, где ему нужно ждать выполнения какого-либо события (например, установки предиката в определенное значение)

·  Поток ждет условную переменную

o  Освобождение мьютекса

o  Ожидание изменения предиката с использованием условной переменной

·  Другой поток производит вычисления, меняет значение предиката, сообщает об этом ждущему потоку, производя следующие действия

o  Захват мьютекса

o  Изменение предиката

o  Сигнализация через условную переменную

o  Освобождение мьютекса

Функции для работы с условными переменными

Функция

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

Описание

Создание и инициализация новой условной переменной. Идентификатор созданной условной переменной возвращается через параметр cond.

Функция

int pthread_cond_destroy(pthread_cond_t *cond);

Описание

Уничтожение условной переменной cond, освобождение выделенной ранее памяти.

Функция

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

Описание

Блокировка вызывающего потока до вызова из другого потока функции pthread_cond_signal или pthread_cond_broadcast. Эта функция должна вызываться после захвата мьютекса; она освобождает мьютекс на все время ожидания.

Функция

int pthread_cond_signal(pthread_cond_t *cond);

Описание

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

Функция

int pthread_cond_broadcast(pthread_cond_t *cond);

Описание

Эта функция используется взамен pthread_cond_signal, если нужно разбудить сразу все усыпленные потоки.

Пример 3. Использование условной переменной.

#include <pthread.h>

#include <stdio.h>

void* compute_thread (void*);

pthread_mutex_t my_sync;

pthread_cond_t rx;

int thread_done = 0;

int x=1;

main( )

{

pthread_t tid;

pthread_attr_t attr;

pthread_attr_init (&attr);

pthread_mutex_init (&my_sync, NULL);

pthread_cond_init (&rx, NULL);

pthread_create(&tid, &attr, compute_thread, (void *)NULL);

pthread_mutex_lock(&my_sync);