Какой-то простой C-код, который я не могу понять - что здесь делает мьютекс? - PullRequest
1 голос
/ 08 февраля 2011

Извините, только что нашел этот код здесь - http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html, и мьютекс был объяснен с этим кодом, но он прошел немного над моей головой Я понимаю функцию мьютекса и то, что он защищает общую переменную во время ее критической секции. Подробности здесь сбивают меня с толку, хотя! Насколько я понимаю, мы создаем новый поток с pthread_create, он запускает процесс functionC, который увеличивает счетчик. Счетчик является защищенной переменной, и, поскольку обе функции работают одновременно, счетчик вернет неправильное значение, если он не был защищен мьютексом.

Это правильно / близко? Большое спасибо:).

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *functionC();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int  counter = 0;

main()
{
   int rc1, rc2;
   pthread_t thread1, thread2;

   /* Create independent threads each of which will execute functionC */

   if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) )
   {
      printf("Thread creation failed: %d\n", rc1);
   }

   if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) )
   {
      printf("Thread creation failed: %d\n", rc2);
   }

   /* Wait till threads are complete before main continues. Unless we  */
   /* wait we run the risk of executing an exit which will terminate   */
   /* the process and all threads before the threads have completed.   */

   pthread_join( thread1, NULL);
   pthread_join( thread2, NULL); 

   exit(0);
}

void *functionC()
{
   pthread_mutex_lock( &mutex1 );
   counter++;
   printf("Counter value: %d\n",counter);
   pthread_mutex_unlock( &mutex1 );
}

Ответы [ 3 ]

3 голосов
/ 08 февраля 2011

Если у вас нет мьютекса, вот что может произойти:

// initialization
counter = 0;

// thread 1 runs:
counter++;

// context switch
// thread 2 runs:
counter++;

// context switch
// thread 1 runs and printf "Counter value: 2"
printf("Counter value: %d\n",counter);

// context switch
// thread 2 runs and printf "Counter value: 2"
printf("Counter value: %d\n",counter);

Итак, вы можете получить такой вывод:

Counter value: 2
Counter value: 2

Теперь,с мьютексом на месте вы убедитесь, что инкремент и его печать будут выполняться атомарно, поэтому вы на 100% уверены, что результат будет:

Counter value: 1
Counter value: 2

Но никогда:

Counter value: 2
Counter value: 2
3 голосов
/ 08 февраля 2011

Ваше объяснение совершенно верно.Если более чем один поток попытался изменить counter одновременно, обновление может быть потеряно.

1 голос
/ 08 февраля 2011

Да, вы правы. Мьютекс не позволяет потокам наступать друг на друга, когда они пытаются увеличить счетчик.

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

Операторы соединения в конце просто гарантируют, что основная программа и оба потока завершатся одновременно. В противном случае основная программа закроется, а потоки останутся зависшими.

...