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

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

Жанры

UNIX: разработка сетевых приложений
Шрифт:

int ndone; /* количество потоков, завершивших выполнение */

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

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

void* do_get_read(void *vptr) {

...

Pthread_mutex_lock(&ndone_mutex);

ndone++;

Pthread_mutex_unlock(&ndone_mutex);

return(fptr); /*
завершение выполнения потока */

}

Но каким при этом получается основной цикл? Взаимное исключение должно быть постоянно блокировано основным циклом, который проверяет, какие потоки завершили свое выполнение.

while (nlefttoread > 0) {

while (nconn < maxnconn && nlefttoconn > 0) {

/* находим файл для чтения */

...

}

/* Проверяем, не завершен ли поток */

Pthread_mutex_lock(&ndone_mutex);

if (ndone > 0) {

for (i =0; i < nfiles; i++) {

if (file[i].f_flags & F_DONE) {

Pthread_join(file[i].f_tid, (void**)&fptr);

/* обновляем file[i] для завершенного потока */

...

}

}

}

Pthread_mutex_unlock(&ndone_mutex);

}

Это означает, что главный поток никогдане переходит в спящее состояние, а просто входит в цикл, проверяя каждый раз значение переменной

ndone
. Этот процесс называется опросом( polling) и рассматривается как пустая трата времени центрального процессора.

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

В терминах Pthreads условная переменная — это переменная типа

pthread_cond_t
. Такие переменные используются в следующих двух функциях:

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t * cptr, pthread_mutex_t * mptr);

int pthread_cond_signal(pthread_cond_t * cptr);

Обе
функции возвращают: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки

Слово

signal
в названии второй функции не имеет отношения к сигналам Unix
SIGxxx
.

Проще всего объяснить действие этих функций на примере. Вернемся к нашему примеру веб-клиента. Счетчик

ndone
теперь ассоциируется и с условной переменной, и с взаимным исключением:

int ndone;

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER;

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

Pthread_mutex_lock(&ndone_mutex);

ndone++;

Pthread_cond_signal(&ndone_cond);

Pthread_mutex_unlock(&ndone_mutex);

Затем основной цикл блокируется в вызове функции

pthread_cond_wait
, ожидая оповещения о завершении выполнения потока:

while (nlefttoread > 0) {

while (nconn < maxnconn && nlefttoconn > 0) {

/* находим файл для чтения */

...

}

/* Ждем завершения выполнения какого-либо потока */

Pthread_mutex_lock(&ndone_mutex);

while (ndone == 0)

Pthread_cond_wait(&ndone_cond, &ndone_mutex);

for (i = 0; i < nfiles; i++) {

if (file[i].f_flags & F_DONE) {

Pthread_join(file[i].f_tid, (void**)&fptr);

/* обновляем file[i] для завершенного потока */

...

}

}

Pthread_mutex_unlock(&ndone_mutex);

}

Обратите внимание на то, что переменная

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

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

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Метатель. Книга 2

Тарасов Ник
2. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель. Книга 2

Безумный Макс. Ротмистр Империи

Ланцов Михаил Алексеевич
2. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
4.67
рейтинг книги
Безумный Макс. Ротмистр Империи

Болотник

Панченко Андрей Алексеевич
1. Болотник
Фантастика:
попаданцы
альтернативная история
6.50
рейтинг книги
Болотник

Темный Лекарь 6

Токсик Саша
6. Темный Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Темный Лекарь 6

Архил...? Книга 2

Кожевников Павел
2. Архил...?
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Архил...? Книга 2

Целитель

Первухин Андрей Евгеньевич
1. Целитель
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Целитель

Ты всё ещё моя

Тодорова Елена
4. Под запретом
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Ты всё ещё моя

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Фараон

Распопов Дмитрий Викторович
1. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Фараон

На изломе чувств

Юнина Наталья
Любовные романы:
современные любовные романы
6.83
рейтинг книги
На изломе чувств

Энфис 2

Кронос Александр
2. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 2