Pthread Mutex lock unlock by different threads

2019-01-14 03:27发布

问题:

A Naive question ..

I read before saying - "A MUTEX has to be unlocked only by the thread that locked it."

But I have written a program where THREAD1 locks mutexVar and goes for a sleep. Then THREAD2 can directly unlock mutexVar do some operations and return.

==> I know everyone say why I am doing so ?? But my question is - Is this a right behaviour of MUTEX ??

==> Adding the sample code

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);
   } 

回答1:

What you've done is simply not legal, and the behavior is undefined. Mutexes only exclude threads that play by the rules. If you tried to lock mutex1 from thread 2, the thread would be blocked, of course; that's the required thing to do. There's nothing in the spec that says what happens if you try to unlock a mutex you don't own!



回答2:

Pthreads has 3 different kinds of mutexes: Fast mutex, recursive mutex, and error checking mutex. You used a fast mutex which, for performance reasons, will not check for this error. If you use the error checking mutex on Linux you will find you get the results you expect.

Below is a small hack of your program as an example and proof. It locks the mutex in main() and the unlock in the created thread will fail.

#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);
}


回答3:

A mutex is used to prevent multiple threads from executing code that is only safe for one thread at a time.

To do this a mutex has several features:

  1. A mutex can handle the race conditions associated with multiple threads trying to "lock" the mutex at the same time and always results with one thread winning the race.

  2. Any thread that loses the race gets put to sleep permanently until the mutex is unlocked. The mutex maintains a list of these threads.

  3. A will hand the "lock" to one and only one of the waiting threads when the mutex is unlocked by the thread who was just using it. The mutex will wake that thread.

If that type of pattern is useful for some other purpose then go ahead and use it for a different reason.

Back to your question. Lets say you were protecting some code from multiple thread accesses with a mutex and lets say 5 threads were waiting while thread A was executing the code. If thread B (not one of the ones waiting since they are permanently slept at the moment) unlocks the mutex, another thread will commence executing the code at the same time as thread A. Probably not desired.

Maybe if we knew what you were thinking about using the mutex for we could give a better answer. Are you trying to unlock a mutex after a thread was canceled? Do you have code that can handle 2 threads at a time but not three and there is no mutex that lets 2 threads through at a time?