Читать интересную книгу Основы программирования в Linux - Мэтью Нейл

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 217 218 219 220 221 222 223 224 225 ... 324

<b>#include &lt;рthread.h&gt;</b>

<b>int pthread_mutex_init(pthread_mutex_t* mutex,</b>

<b> const pthread_mutexattr_t *mutexattr);</b>

<b>int pthread_mutex_lock(pthread_mutex_t* mutex);</b>

<b>int pthread_mutex_unlock(pthread mutex_t* mutex);</b>

<b>int pthread_mutex_destroy(pthread_mutex_t *mutex);</b>

Как обычно, в случае успешного завершения возвращается 0 и код ошибки в случае аварийного завершения, но переменная errno не задается, вам придется использовать код возврата.

Как и функции семафоров, функции мьютексов принимают указатель на предварительно объявленный объект, в данном случае типа pthread_mutex_t. Дополнительный параметр атрибутов в функции pthread_mutex_init позволяет задать атрибуты мьютекса, управляющие его поведением. По умолчанию тип атрибута — "fast". У него есть небольшой недостаток: если ваша программа попытается вызвать функцию pthread_mutex_lock для мьютекса, который уже заблокирован, программа блокируется. Поскольку поток, удерживающий блокировку, в данный момент заблокирован, мьютекс никогда не будет открыт, и программа попадает в тупиковую ситуацию. Есть возможность изменить атрибуты мьютекса так, чтобы он либо проверял наличие такой ситуации и возвращал ошибку, либо действовал рекурсивно и разрешал множественные блокировки тем же самым потоком, если будет такое же количество разблокировок в дальнейшем.

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

Выполните упражнение 12.4. 

Упражнение 12.4. Мьютекс потока

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

#include &lt;stdio.h&gt;

#include &lt;unistd.h&gt;

#include &lt;stdlib.h&gt;

#include &lt;string.h&gt;

#include &lt;pthread.h&gt;

#include &lt;semaphore.h&gt;

void *thread_function(void *arg);

pthread_mutex_t work_mutex; /* защищает work_area и time_to_exit */

#define WORK_SIZE 1024

char work_area[WORK_SIZE];

int time_to_exit = 0;

int main() {

 int res;

 pthread_t a_thread;

 void *thread_result;

 res = pthread_mutex_init(&amp;work_mutex, NULL);

 if (res != 0) {

  perror(&quot;Mutex initialization failed&quot;);

  exit(EXIT_FAILURE);

 }

 res pthread_create(&amp;a_thread, NULL, thread_function, NULL);

 if (res != 0) {

  perror(&quot;Thread creation failed&quot;);

  exit(EXIT_FAILURE);

 }

 pthread_mutex_lock(&amp;work_mutex);

 printf(&quot;Input same text. Enter 'end' to finishn&quot;);

 while (!time_to_exit) {

  fgets (work_area, WORK_SIZE, stdin);

  pthread_mutex_unlock(&amp;work_mutex);

  while(1) {

   pthread_mutex_lock(&amp;work_mutex);

   if (work_area[0] != '') {

    pthread_mutex_unlock(&amp;work_mutex);

    sleep(1);

   } else {

    break;

   }

  }

 }

 pthread_mutex_unlock(&amp;work_mutex);

 printf(&quot;nWaiting for thread to finish...n&quot;);

 res = pthread_join(a_thread, &amp;thread_result);

 if (res ! = 0) {

  perror(&quot;Thread join failed&quot;);

  exit(EXIT_FAILURE);

 }

 printf(&quot;Thread joinedn&quot;);

 pthread_mutex_destroy(&amp;work_mutex);

 exit(EXIT_SUCCESS);

}

void *thread_function(void *arg) {

 sleep(1);

 pthread_mutex_lock(&amp;work_mutex);

 while(strncmp(&quot;end&quot;, work_area, 3) ! = 0) {

  printf(&quot;You input %d charactersn&quot;, strlen(work_area)-1);

  work_area[0] = '';

  pthread_mutex_unlock(&amp;work_mutex);

  sleep(1);

  pthread_mutex_lock(&amp;work_mutex);

  while (work_area[0] == '') {

   pthread_mutex_unlock(&amp;work_mutex);

   sleep(1);

1 ... 217 218 219 220 221 222 223 224 225 ... 324
На этом сайте Вы можете читать книги онлайн бесплатно русская версия Основы программирования в Linux - Мэтью Нейл.

Оставить комментарий