Pthread Mutex блокировка разблокировки разными нитями - PullRequest
15 голосов
/ 28 марта 2011

Наивный вопрос ..

Я прочитал перед тем, как сказать: " MUTEX должен быть разблокирован только тем потоком, который его заблокировал. "

Но я написал программу, в которой THREAD1 блокирует mutexVar и отправляется спать. Затем THREAD2 может напрямую разблокировать mutexVar, выполнить некоторые операции и вернуться.

==> Я знаю, что все говорят, почему я так делаю ?? Но мой вопрос - это правильное поведение MUTEX ??

==> Добавление примера кода

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

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

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

   if(pthread_mutex_init(&mutex1, NULL))
   printf("Error while using pthread_mutex_init\n");

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

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

Ответы [ 3 ]

21 голосов
/ 31 марта 2011

Pthreads имеет 3 различных типа мьютексов: быстрый мьютекс, рекурсивный мьютекс и мьютекс с проверкой ошибок. Вы использовали быстрый мьютекс, который по соображениям производительности не будет проверять эту ошибку. Если вы используете мьютекс для проверки ошибок в Linux, вы получите ожидаемые результаты.

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

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

/*** NOTE THE ATTR INITIALIZER HERE! ***/
pthread_mutex_t mutex1 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

int counter = 0;


void *functionD(void* data)
{
   int rc;

   if ((rc = pthread_mutex_unlock(&mutex1)) != 0)
   {
       errno = rc;
       perror("other thread unlock result");
       exit(1);
   }

   pthread_mutex_lock(&mutex1);
   counter=10;
   printf("Thread02: Counter value: %d\n",counter);

   return(data);
}


int main(int argc, char *argv[])
{
   int rc1;
   pthread_t thread1;

   if ((rc1 = pthread_mutex_lock(&mutex1)) != 0)
   {
       errno = rc1;
       perror("main lock result");
   }

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

   pthread_join(thread1, NULL);
}
20 голосов
/ 28 марта 2011

То, что вы сделали, просто не разрешено законом, а поведение не определено.Мьютексы исключают только темы, которые играют по правилам.Если вы попытаетесь заблокировать mutex1 из потока 2, поток, конечно, будет заблокирован;это обязательная вещь.В спецификации ничего не говорится о том, что произойдет, если вы попытаетесь разблокировать мьютекс, который вам не принадлежит!

0 голосов
/ 07 апреля 2011

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

Для этого мьютекс имеет несколько функций:

  1. Мьютекс может обрабатывать условия гонки, связанные с несколькими потоками, пытающимися «заблокировать» мьютекс одновременно, и всегда приводит к тому, что один поток выигрывает гонку.

  2. Любой поток, который проигрываетрасу усыпляют навсегда, пока мьютекс не будет разблокирован.Мьютекс поддерживает список этих потоков.

  3. A передает «блокировку» одному и только одному из ожидающих потоков, когда мьютекс разблокирован потоком, который только что использовал его.,Мьютекс разбудит этот поток.

Если этот тип паттерна полезен для какой-то другой цели, продолжайте и используйте его по другой причине.

Назад к вашемувопрос.Допустим, вы защищали некоторый код от многопотокового доступа с помощью мьютекса и, скажем, 5 потоков ожидали, пока поток А выполнял код.Если поток B (не один из тех, кто ожидает, так как они постоянно спят в данный момент) разблокирует мьютекс, другой поток начнет выполнять код в то же время, что и поток A. Вероятно, это нежелательно.

Возможно, еслимы знали, что вы думаете об использовании мьютекса, потому что мы могли бы дать лучший ответ.Вы пытаетесь разблокировать мьютекс после отмены потока?Есть ли у вас код, который может обрабатывать 2 потока одновременно, но не три, и нет мьютекса, пропускающего 2 потока одновременно?

...