Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

Стивенс Уильям Ричард

Шрифт:

4 /* глобальные переменные для всех потоков */

5 int nitems; /* только для чтения потребителем и производителем */

6 int buff[MAXNITEMS];

7 struct {

8 pthread_mutex_t mutex;

9 int nput; /* следующий сохраняемый элемент */

10 int nval; /* следующее сохраняемое значение */

11 } put = {

12 PTHREAD_MUTEX_INITIALIZER

13 };

14 struct {

15 pthread_mutex_t mutex:

16 pthread_cond_t cond;

17 int nready; /* количество готовых для потребителя */

18 } nready = {

19 PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER

20 };

Функции produce и consume претерпевают некоторые изменения. Их текст дан в листинге 7.6.

Листинг 7.6. Функции produce и consume

//mutex/prodcons6.c

46 void *

47 produce(void *arg)

48 {

49 for (;;) {

50 Pthread_mutex_lock(&put.mutex);

51 if (put.nput >= nitems) {

52 Pthread_mutex_unlock(&put.mutex);

53 return(NULL); /* массив заполнен, готово */

54 }

55 buff[put.nput] = put.nval;

56 put.nput++;

57 put.nval++;

58 Pthread_mutex_unlock(&put.mutex);

59 Pthread_mutex_lock(&nready.mutex):

60 if (nready.nready == 0)

61 Pthread_cond_signal(&nready.cond);

62 nready.nready++;

63 Pthread_mutex_unlock(&nready.mutex);

64 *((int *) arg) += 1;

65 }

66 }

67 void*

68 consume(void *arg)

69 {

70 int i;

71 for (i = 0; i < nitems; i++) {

72 Pthread_mutex_lock(&nready.mutex);

73 while (nready.nready == 0)

74 Pthread_cond_wait(&nready.cond, &nready.mutex);

75 nready.nready--;

76 Pthread_mutex_unlock(&nready.mutex);

77 if (buff[i] != i)

78 printf("buff[%d] = *d\n", i, buff[i]);

79 }

80 return(NULL);

81 }

Помещение очередного элемента в массив

50-58 Для блокирования критической области в потоке-производителе теперь используется исключение put.mutex. 

Уведомление потребителя

59-64 Мы увеличиваем счетчик nready.nready, в котором хранится количество элементов, готовых для обработки потребителем. Перед его увеличением мы проверяем, не было ли значение счетчика нулевым, и если да, то вызывается функция pthread_cond_signal, позволяющая возобновить выполнение всех потоков (в данном случае потребителя), ожидающих установки ненулевого значения этой переменной. Теперь мы видим, как взаимодействуют взаимное исключение и связанная с ним условная переменная. Счетчик используется совместно потребителем и производителями, поэтому доступ к нему осуществляется с блокировкой соответствующего взаимного исключения (nready.mutex). Условная переменная используется для ожидания и передачи сигнала.

Потребитель ждет, пока значение nready.nready не станет отличным от нуля

72-76 Потребитель просто ждет, пока значение счетчика nready. nready не станет отличным от нуля. Поскольку этот счетчик используется совместно с производителями, его значение можно проверять только при блокировке соответствующего взаимного исключения. Если при проверке значение оказывается нулевым, мы вызываем pthread_cond_wait для приостановки процесса. При этом выполняются два атомарных действия:

1. Разблокируется nready.mutex.

2. Выполнение потока приостанавливается, пока какой-нибудь другой поток не вызовет pthread_cond_signal для этой условной переменной.

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

  • Читать дальше
  • 1
  • ...
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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