1
votes

Recently I read some code about thread mutex, releated code is here:

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

  pthread_mutex_t mutex;
  pthread_cond_t cond;
  pthread_t thread;

  void fn(void *arg)
  {
  3     pthread_mutex_lock(&mutex);
        printf( "signal before\n" );
  4     pthread_cond_signal(&cond);
        printf( "signal after\n" );
        pthread_mutex_unlock(&mutex);
  }
  int main()
  {
        int err1;
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond,NULL);

  1     pthread_mutex_lock(&mutex);
  2     err1 = pthread_create(&thread, NULL, fn, NULL);
        usleep(1);
        pthread_cond_wait(&cond,&mutex);
        printf( "main thread get signal\n");
        pthread_mutex_unlock(&mutex);
        pthread_join(thread, NULL);
        pthread_mutex_destroy( &mutex );
        pthread_cond_destroy( &cond );
  }     

In main thread, first I call pthread_mutex_lock function locks the mutex in num 1, after I create a child thread in num 2, and in the child thread start function void fn( void *arg) I call pthread_mutex_lock in num 3 again, In theory it should block until mutex (main thread) is freed, but why can it continue to execute code in num 4 in child thread ?

execute result:

result_pic

gcc version

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1 Apple LLVM version 7.3.0 (clang-703.0.31) Target: x86_64-apple-darwin15.4.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Thanks very much.

1
Could you please reformulate your question because right now it is hard to tell what you are asking?ixSci
What type is flag? How is it initialized? What behavior are you observing? What behavior do you expect? (Also, the way you're using pthread_cond_signal and pthread_cond_wait will produce unpredictable results because the state of the predicate isn't stored anywhere. So you might want to explain why you expect what you expect so that if your reasoning is incorrect, we can explain why and where.)David Schwartz
@DavidSchwartz flag type is int, I am confused that main thread call pthread_mutex_lock locks the mutex first and why child thread call pthread_mutex_lock not block as aspectjefby
@ixSci I edit it just now.jefby

1 Answers

1
votes

The purpose of a condition variable is to permit threads to wait for things to happen in other threads. The problem with doing this with a mutex is that the following code doesn't work:

  1. Acquire the lock that protects the shared state.
  2. See if we need to wait, if so wait.

Oops. Now we're waiting while we hold the lock. So no other thread can change the shared state. So we'll wait forever. Let's try it again, this time releasing the lock:

  1. Acquire the lock that protects the shared state.
  2. If we need to wait, release the lock and wait.

Oops, we still have a problem. What if the thing we're waiting for happens after we release the lock but before we begin waiting? Again, we'll wait forever.

So we need an atomic "unlock and wait" function to make step 2 work. That's what pthread_cond_wait is. So the mutex is released while the thread is waiting.

The canonical use of pthread_cond_wait is:

 pthread_mutex_lock(&mutex);
 while (we_need_to_wait)
     pthread_cond_wait(&cond, &mutex);
 // possibly do some stuff while we still hold the mutex
 pthread_mutex_unlock(&mutex);

Notice this allows us to decide to wait while we still hold the mutex, wait without holding the mutex, but have no window for a race condition where the mutex is released but we're not yet waiting.

By the way, it's extremely difficult to use a condition variable sanely any other way. So you really shouldn't attempt to use pthread_cond_wait in any other pattern until you have a rock solid understanding of how condition variables work. Make absolutely sure you always know precisely what you're waiting for and the thing you're waiting for is protected by the mutex that you pass to pthread_cond_wait.