Is is sensible to unlock a mutex and immediately re-lock it? Consider this example:
pthread_mutex_lock(mutex); while(1) { /* Do work. */ pthread_mutex_unlock(mutex); pthread_mutex_lock(mutex); }
The intention here is to make other threads wait until we've finished doing work. Then we give them a chance to get in before we go round again and do more work. But can we guarantee that the scheduler will allow another thread to get in when we unlock a mutex? Is it possible that this thread will immediately re-lock the mutex, and never give other threads a chance to get in?
If that's possible, then it would make sense to put an explicit yield between the calls to unlock and then lock:
pthread_mutex_lock(mutex); while(1) { /* Do work. */ pthread_mutex_unlock(mutex); sched_yield(); pthread_mutex_lock(mutex); }
So, is the explicit yield necessary, or even desireable? This is what the POSIX standard has to say:
The pthread_mutex_unlock() function shall release the mutex object referenced by mutex...If there are threads blocked on the mutex object referenced by mutex whenpthread_mutex_unlock() is called, resulting in the mutex becoming available, the schedulingpolicy shall determine which thread shall acquire the mutex.from the Single Unix Spec. IEEE Std 1003.1, 2004
This says that a call to unlock() must cause the scheduler to re-consider which thread to run. That guarantees another thread waiting on the mutex the chance to get in.
Experimentation (on HP-UX, Linux, Tru64, OSX and AIX) shows that the explicit yield() is never needed. Indeed it sometimes has a dramatically adverse affect on performance. On Linux, OSX and AIX, a thread which yields gets up to 10,000 times less CPU time than a thread that does not yield!