Mutexes provide a mechanism for allowing one thread to block the execution of another.This opens up the possibility of a new class of bugs, called deadlocks. A deadlock occurs when one or more threads are stuck waiting for something that never will occur.
A simple type of deadlock may occur when the same thread attempts to lock a mutex twice in a row. The behavior in this case depends on what kind of mutex is being used.Three kinds of mutexes exist:
■ Locking a fast mutex (the default kind) will cause a deadlock to occur. An attempt to lock the mutex blocks until the mutex is unlocked. But because the thread that locked the mutex is blocked on the same mutex, the lock cannot ever be released.
■ Locking a recursive mutex does not cause a deadlock. A recursive mutex may safely be locked many times by the same thread. The mutex remembers how many times pthread_mutex_lock was called on it by the thread that holds the lock; that thread must make the same number of calls to pthread_mutex_unlock before the mutex is actually unlocked and another thread is allowed to lock it.
■ GNU/Linux will detect and flag a double lock on an error-checking mutex that would otherwise cause a deadlock. The second consecutive call to pthread_mutex_lock returns the failure code EDEADLK.
By default, a GNU/Linux mutex is of the fast kind. To create a mutex of one of the other two kinds, first create a mutex attribute object by declaring a pthread_mutexattr_t variable and calling pthread_mutexattr_init on a pointer to it.Then set the mutex kind by calling pthread_mutexattr_setkind_np; the first argument is a pointer to the mutex attribute object, and the second is PTHREAD_MUTEX_RECURSIVE_NP for a recursive mutex, or PTHREAD_MUTEX_ERRORCHECK_NP for an error-checking mutex. Pass a pointer to this attribute object to pthread_mutex_init to create a mutex of this kind, and then destroy the attribute object with pthread_mutexattr_destroy.
This code sequence illustrates creation of an error-checking mutex, for instance: pthread_mutexattr_t attr; pthread_mutex_t mutex;
pthread_mutexattr_setkind_np (&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init (&mutex, &attr); pthread_mutexattr_destroy (&attr);
As suggested by the "np" suffix, the recursive and error-checking mutex kinds are specific to GNU/Linux and are not portable. Therefore, it is generally not advised to use them in programs. (Error-checking mutexes can be useful when debugging, though.)
Was this article helpful?