Чтение онлайн

на главную - закладки

Жанры

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

Самьюэл Алекс

Шрифт:

Похожая функция

pthread_cond_broadcast
разблокирует все потоки, ожидающие данного сигнала.

■ Функция

pthread_cond_wait
блокирует вызывающий ее поток до тех пор, пока не будет получен сигнал об изменении заданной переменной. Первым ее аргументом является указатель на объект типа
pthread_cond_t
. Второй аргумент — это указатель на объект исключающего семафора (тип
pthread_mutex_t
).

В момент вызова функции

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

Перечисленные ниже этапы должны выполняться всякий раз, когда программа тем или иным способом меняет результат проверки условия, контролируемого сигнальной переменной (в нашей программе условие — это значение флага):

1. Захватить исключающий семафор, дополняющий сигнальную переменную.

2. Выполнить действие, включающее изменение результата проверки условия (в нашем случае — установить флаг).

3. Послать сигнал (возможно, широковещательный) об изменении условия.

4. Освободить исключающий семафор.

В листинге 4.14 показана измененная версия предыдущего примера, в которой на этот раз флаг защищается сигнальной переменной. Обратите внимание на то, что в функции

thread_function
исключающий семафор захватывается до того, как будет проверено значение переменной
thread_flag
. Захват автоматически снимается функцией
pthread_cond_wait
перед тем, как поток оказывается заблокированным, и также автоматически восстанавливается по завершении функции:

Листинг 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
можно разблокировать произвольное число потоков.

4.4.7. Взаимоблокировки двух и более потоков

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

Поделиться:
Популярные книги

Моя на одну ночь

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
5.50
рейтинг книги
Моя на одну ночь

Черный Маг Императора 8

Герда Александр
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8

Измена. Отбор для предателя

Лаврова Алиса
1. Отбор для предателя
Фантастика:
фэнтези
5.00
рейтинг книги
Измена. Отбор для предателя

Кодекс Крови. Книга II

Борзых М.
2. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга II

Шаг в бездну

Муравьёв Константин Николаевич
3. Перешагнуть пропасть
Фантастика:
фэнтези
космическая фантастика
7.89
рейтинг книги
Шаг в бездну

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Хроники странного королевства. Вторжение. (Дилогия)

Панкеева Оксана Петровна
110. В одном томе
Фантастика:
фэнтези
9.38
рейтинг книги
Хроники странного королевства. Вторжение. (Дилогия)

Часовой ключ

Щерба Наталья Васильевна
1. Часодеи
Фантастика:
фэнтези
9.36
рейтинг книги
Часовой ключ

Инвестиго, из медика в маги

Рэд Илья
1. Инвестиго
Фантастика:
фэнтези
городское фэнтези
попаданцы
5.00
рейтинг книги
Инвестиго, из медика в маги

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Очешуеть! Я - жена дракона?!

Амеличева Елена
Фантастика:
юмористическая фантастика
5.43
рейтинг книги
Очешуеть! Я - жена дракона?!

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9