Reentrant mutex
Encyclopedia
A reentrant mutex is a mutual exclusion
mechanism. In a reentrant mutex, the same thread can acquire the lock
multiple times. However, the lock must be released the same number of times or else other threads will be unable to acquire the lock.
A reentrant mutex has some similarities to a counting semaphore
.
Recursive locks (also called recursive thread mutex) are those that allow a thread to recursively acquire the same lock that it is holding. Note that this behavior is different from a normal lock. In the normal case if a thread that is already holding a normal lock attempts to acquire the same lock again, then it will deadlock. Recursive locks behave exactly like normal locks when another thread tries to acquire a lock that is already being held. Note that the recursive lock is said to be released if and only if the number of times it has been acquired matches the number of times it has been released by the owner thread. Many operating systems do not provide these recursive locks natively. Hence, it is necessary to emulate the behavior using primitive features like mutexes (locks) and condition variables
.
A big form of criticism on recursive mutexes is that when used in combination with condition variables, the semantics are not clearly defined. Say, the condition variable would not recursively unlock the mutex, the system could run into a deadlock. On the other hand, if the mutex would be recursively unlocked, it would unlock all critical sections, even though simple inspection of code wouldn't reveal this. Therefore several implementations, such as the mutexes and condition variables used inside the FreeBSD
kernel, don't allow waiting on a condition variable if the calling process has acquired more than one lock.
Java's native synchronization mechanisms have used recursive locks since Java's inception in about 1997. A lock is syntactically just a block of code with the 'synchronized' keyword preceding it and any Object reference in parentheses that will be used as the mutex. Inside the synchronized block, the given object can be used as a condition variable by doing a wait, notify, or notifyAll on it. Thus all Objects are both recursive mutexes and condition variables. The newer Java versions provide additional primitives in the form of AtomicIntegers and AtomicBooleans and so on, which are lower-level and faster, and which can be used to construct spin-lock types of structures that allow multi-core programming, where mutexes and condition variables fail.
Mutual exclusion
Mutual exclusion algorithms are used in concurrent programming to avoid the simultaneous use of a common resource, such as a global variable, by pieces of computer code called critical sections. A critical section is a piece of code in which a process or thread accesses a common resource...
mechanism. In a reentrant mutex, the same thread can acquire the lock
Lock (computer science)
In computer science, a lock is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. Locks are one way of enforcing concurrency control policies.-Types:...
multiple times. However, the lock must be released the same number of times or else other threads will be unable to acquire the lock.
A reentrant mutex has some similarities to a counting semaphore
Semaphore (programming)
In computer science, a semaphore is a variable or abstract data type that provides a simple but useful abstraction for controlling access by multiple processes to a common resource in a parallel programming environment....
.
Recursive locks (also called recursive thread mutex) are those that allow a thread to recursively acquire the same lock that it is holding. Note that this behavior is different from a normal lock. In the normal case if a thread that is already holding a normal lock attempts to acquire the same lock again, then it will deadlock. Recursive locks behave exactly like normal locks when another thread tries to acquire a lock that is already being held. Note that the recursive lock is said to be released if and only if the number of times it has been acquired matches the number of times it has been released by the owner thread. Many operating systems do not provide these recursive locks natively. Hence, it is necessary to emulate the behavior using primitive features like mutexes (locks) and condition variables
Monitor (synchronization)
In concurrent programming, a monitor is an object or module intended to be used safely by more than one thread. The defining characteristic of a monitor is that its methods are executed with mutual exclusion. That is, at each point in time, at most one thread may be executing any of its methods...
.
A big form of criticism on recursive mutexes is that when used in combination with condition variables, the semantics are not clearly defined. Say, the condition variable would not recursively unlock the mutex, the system could run into a deadlock. On the other hand, if the mutex would be recursively unlocked, it would unlock all critical sections, even though simple inspection of code wouldn't reveal this. Therefore several implementations, such as the mutexes and condition variables used inside the FreeBSD
FreeBSD
FreeBSD is a free Unix-like operating system descended from AT&T UNIX via BSD UNIX. Although for legal reasons FreeBSD cannot be called “UNIX”, as the direct descendant of BSD UNIX , FreeBSD’s internals and system APIs are UNIX-compliant...
kernel, don't allow waiting on a condition variable if the calling process has acquired more than one lock.
Java's native synchronization mechanisms have used recursive locks since Java's inception in about 1997. A lock is syntactically just a block of code with the 'synchronized' keyword preceding it and any Object reference in parentheses that will be used as the mutex. Inside the synchronized block, the given object can be used as a condition variable by doing a wait, notify, or notifyAll on it. Thus all Objects are both recursive mutexes and condition variables. The newer Java versions provide additional primitives in the form of AtomicIntegers and AtomicBooleans and so on, which are lower-level and faster, and which can be used to construct spin-lock types of structures that allow multi-core programming, where mutexes and condition variables fail.