A mutex (mutual exclusion) is an object that multiple threads use to ensure the integrity of a shared resource that they access, most commonly shared data. A mutex has two states: locked and unlocked. For each piece of shared data, all threads accessing that data must use the same mutex; each thread locks the mutex before it accesses the shared data and unlocks the mutex when it is finished accessing that data. If the mutex is locked by another thread, the thread requesting the lock is blocked when it tries to lock the mutex if you call pthread_mutex_lock( ) (see the following figure). The blocked thread continues and is not blocked if you call pthread_mutex_trylock( ).
Only One Thread Can Lock a Mutex
Each mutex must be initialized. (To initialize mutexes as part of the program's one-time initialization code, see One-Time Initialization Routines). To initialize a mutex, use the pthread_mutex_init( ) routine. This routine allows you to specify an attributes object, which allows you to specify the mutex type. The following are types of mutexes:
· A fast mutex (the default) is locked only once by a thread. If the thread tries to lock the mutex again without first unlocking it, the thread waits for itself to release the first lock and deadlocks on itself.
This type of mutex is called fast because it can be locked and unlocked more rapidly than a recursive mutex. It is the most efficient form of mutex.
· A recursive mutex can be locked more than once by a given thread without causing a deadlock. The thread must call the pthread_mutex_unlock( ) routine the same number of times that it called the pthread_mutex_lock( ) routine before another thread can lock the mutex. Recursive mutexes have the notion of a mutex owner. When a thread successfully locks a recursive mutex, it owns that mutex and the lock count is set to 1. Any other thread attempting to lock the mutex blocks until the mutex becomes unlocked. If the owner of the mutex attempts to lock the mutex again, the lock count is incremented, and the thread continues running. When an owner unlocks a recursive mutex, the lock count is decremented. The mutex remains locked and owned until the count reaches 0 (zero). It is an error for any thread other than the owner to attempt to unlock the mutex.
A recursive mutex is useful if a thread needs exclusive access to a piece of data, and it needs to call another routine (or itself) that needs exclusive access to the data. A recursive mutex allows nested attempts to lock the mutex to succeed rather than deadlock.
This type of mutex requires more careful programming. Never use a recursive mutex with condition variables because the implicit unlock performed for a pthread_cond_wait( ) or pthread_cond_timedwait( ) may not actually release the mutex. In that case, no other thread can satisfy the condition of the predicate.
· A nonrecursive mutex is locked only once by a thread, like a fast mutex. If the thread tries to lock the mutex again without first unlocking it, the thread receives an error. Thus, nonrecursive mutexes are more informative than fast mutexes because fast mutexes block in such a case, leaving it up to you to determine why the thread no longer executes. Also, if someone other than the owner tries to unlock a nonrecursive mutex, an error is returned.
To lock a mutex, use one of the following routines, depending on what you want to happen if the mutex is locked:
· The pthread_mutex_lock( ) routine
If the mutex is locked, the thread waits for the mutex to become available.
· The pthread_mutex_trylock( ) routine
If the mutex is locked, the thread continues without waiting for the mutex to become available. The thread immediately checks the return status to see if the lock was successful, and then takes whatever action is appropriate if it was not.
When a thread is finished accessing a piece of shared data, it unlocks the associated mutex by calling the pthread_mutex_unlock( ) routine.
If another thread is waiting on the mutex, its execution is unblocked. If more than one thread is waiting on the mutex, the scheduling policy and the thread scheduling priority determine which thread acquires the mutex.
You can delete a mutex and reclaim its storage by calling the pthread_mutex_destroy( ) routine. Use this routine only after the mutex is no longer needed by any thread. Mutexes are automatically deleted when the program terminates.