Date

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 when
pthread_mutex_unlock() is called, resulting in the mutex becoming available, the scheduling
policy 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!