Reputation: 365
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 ?
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.
Upvotes: 1
Views: 3559
Reputation: 182761
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:
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:
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
.
Upvotes: 1