Книга: Программирование для Linux. Профессиональный подход

Листинг 4.14. (condvar.c) Управление работой потока с помощью сигнальной переменной

Листинг 4.14. (condvar.c) Управление работой потока с помощью сигнальной переменной

#include <pthread.h>
int thread_flag;
pthread_cond_t thread_flag_cv;
pthread_mutex_t thread_flag_mutex;
void initialize_flag() {
 /* Инициализация исключающего семафора и сигнальной
    переменной. */
 pthread_mutex_init(&thread_flag_mutex, NULL);
 pthread_cond_init(&thread_flag_cv, NULL);
 /* Инициализация флага. */
 thread_flag = 0;
}
/* Если флаг установлен, многократно вызывается функция
   do_work(). В противном случае поток блокируется. */
void* thread_function(void* thread_arg) {
 /* Бесконечный цикл. */
 while (1) {
  /* Захватываем исключающий семафор, прежде чем обращаться
     к флагу. */
  pthread_mutex_lock(&thread_flag_mutex);
  while (!thread_flag)
   /* Флаг сброшен. Ожидаем сигнала об изменении условной
      переменной, указывающего на то, что флаг установлен.
      При поступлении сигнала поток разблокируется и снова
      проверяет флаг. */
   pthread_cond_wait(&thread_flag_cv, &thread_flag_mutex);
  /* При выходе из цикла освобождаем исключающий семафор. */
  pthread_mutex_unlock(&thread_flag_mutex);
  /* Выполняем требуемые действия. */
  do_work();
 }
 return NULL;
}
/* Задаем значение флага равным FLAG_VALUE. */
void set_thread_flag(int flag_value) {
 /* Захватываем исключающий семафор, прежде чем изменять
    значение флага. */
 pthread_mutex_lock(&thread_flag_mutex);
 /* Устанавливаем флаг и посылаем сигнал функции
    thread_function(), заблокированной в ожидании флага.
    Правда, функция не сможет проверить флаг, пока
    исключающий семафор не будет освобожден. */
 thread_flag = flag_value;
 pthread_cond_signal(&thread_flag_cv);
 /* освобождаем исключающий семафор. */
 pthread_mutex_unlock(&thread_flag_mutex);
}

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

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

Оглавление книги


Генерация: 1.299. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз