Mir-knigi.online
Книги онлайн читать бесплатно!
  • Главная
  • Жанры
  • ТОП книг
  • ТОП авторов
  • Контакты

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

Часть 292 из 399 Информация о книге
ПРИМЕЧАНИЕ

Некоторые системы (например, Solaris) определяют константу PTHREAD_MUTEX_INITIALIZER как 0. Если данная инициализация будет опущена, это ни на что не повлияет, так как статически размещаемые переменные все равно автоматически инициализируются нулем. Но для других систем такой гарантии дать нельзя — например, в Digital Unix константа инициализации ненулевая.

В листинге 26.12 приведена исправленная версия листинга 26.11, в которой используется одно взаимное исключение для блокирования счетчика при работе с двумя потоками.

Листинг 26.12. Исправленная версия листинга 26.11, использующая взаимное исключение для защиты совместно используемой переменной

//threads/examplе01.с

 1 #include "unpthread.h"

 2 #define NLOOP 5000

 3 int counter; /* увеличивается потоками */

 4 pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

 5 void *doit(void*);

 6 int

 7 main(int argc, char **argv)

 8 {

 9  pthread_t tidA, tidB;

10  Pthread_create(&tidA, NULL, &doit, NULL);

11  Pthread_create(&tidB, NULL, &doit, NULL);

12  /* ожидание завершения обоих потоков */

13  Pthread_join(tidA, NULL);

14  Pthread_join(tidB, NULL);

15  exit(0);

16 }

17 void*

18 doit(void *vptr)

19 {

20  int i, val;

21  /*

22   * Каждый поток считывает, выводит и увеличивает счетчик NLOOP раз.

23   * Значение счетчика должно возрастать монотонно.

24   */

25  for (i = 0; i < NLOOP; i++) {

26   Pthread_mutex_lock(&counter_mutex);

27   val = counter;

28   printf(%d: %d\n", pthread_self(), val + 1);

29   counter = val + 1;

30   Pthread_mutex_unlock(&counter_mutex);

31  }

32  return(NULL);

33 }

Мы объявляем взаимное исключение с именем

counter_mutex
. Это исключение должно быть заблокировано потоком на то время, когда он манипулирует переменной counter. Когда мы запускали эту программу, результат всегда был правильным: значение переменной увеличивалось монотонно, а ее окончательное значение всегда оказывалось равным 10 000.

Насколько серьезной является дополнительная нагрузка, связанная с использованием взаимных исключений? Мы изменили программы, приведенные в листингах 26.11 и 26.12, заменив значение

NLOOP
на 50 000 (вместо исходного значения 5000), и засекли время, направив вывод на устройство
/dev/null
. Время работы центрального процессора в случае корректной версии, использующей взаимное исключение, увеличилось относительно времени работы некорректной версии без взаимного исключения на 10 %. Это означает, что использование взаимного исключения не связано со значительными издержками.

26.8. Условные переменные

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

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

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] для завершенного потока */

    ...

   }

  }


Перейти к странице:
Предыдущая страница
Следующая страница
Жанры
  • Военное дело
  • Деловая литература
  • Детективы и триллеры
  • Детские
  • Детские книги
  • Документальная литература
  • Дом и дача
  • Дом и Семья
  • Жанр не определен
  • Зарубежная литература
  • Знания и навыки
  • История
  • Компьютеры и Интернет
  • Легкое чтение
  • Любовные романы
  • Научно-образовательная
  • Образование
  • Поэзия и драматургия
  • Приключения
  • Проза
  • Прочее
  • Психология и мотивация
  • Публицистика и периодические издания
  • Религия и духовность
  • Родителям
  • Серьезное чтение
  • Спорт, здоровье и красота
  • Справочная литература
  • Старинная литература
  • Техника
  • Фантастика и фентези
  • Фольклор
  • Хобби и досуг
  • Юмор
Mir-knigi.online

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

Контакты
  • [email protected]
Информация
  • Карта сайта
© mir-knigi.online, 2026. | Вход