What is Mutex? What is Semaphore? What are the differences between the two, and when should we use the two? Complete understanding of operating system concepts is important if you want to design or develop smart software applications, and one topic that is usually encountered by someone who is designing/developing a smart software application is the comparisons between Mutex and Semaphore. For someone who is new in the world of programming, the two can be a little confusing. However, getting to know when and where to use the two is imperative. Therefore, below, we are going to see the differences and comparisons between Mutex and Semaphore.
What is Mutex?
Mutex actually stands for “mutual exclusion”, a program object that allows multiple program threads to access the same resource, such as a file, but not simultaneously. When the program is started, a Mutex is created and is given a unique name. After this point, whenever any thread needs to use the associated resource, they must lock the Mutex so that it cannot be accessed by other threads as long as they are still using the resource. Once the resource is no longer needed, or the routine is finished, the thread must set the Mutex to unlock.
What is Semaphore?
On the other hand, a Semaphore is an abstract data type or a variable that is used to control the access of multiple threads to a common resource. A simple semaphore could be a plain variable that is incremented, decremented, or toggled according to certain conditions, and is used as a preliminary condition to control the access to a resource. Semaphores can be classified into two groups, counting semaphores and binary semaphores. Counting semaphores are those that allow an arbitrary resource count, whereas binary semaphores are the ones that restrict the possible values to just 0 or 1.
Mutex and Binary Semaphore are Two Different Things!
There is often an ambiguity when speaking about the Mutex and binary semaphores. Some people may even say that the Mutex is a binary semaphore – but that’s wrong! Well, perhaps due to the almost similar implementation, a Mutex is sometimes referred as a binary semaphore. But there are still fundamental differences between a mutex and a binary semaphore.
A Mutex is a locking mechanism, used to synchronize the access to a resource. Only one task (a thread or a process, depending on the OS abstraction) can acquire the Mutex at a time. In other words, there is an ownership that is associated with the Mutex, and only the current owner can release the lock of the Mutex.
On the other hand, a semaphore, be it a counting or binary semaphore, is just a signaling mechanism. It triggers an interrupt so that the interrupt service routine (ISR) will signal the call processing task. There is no ownership – you can signal a semaphore from any thread or process.
An Analogous Example
Imagine a toilet room. A Mutex is a key to a toilet. Only one person can have the key and occupy the toilet at a time. Once the person has finished, the key is released and given to the next person in the queue.
Meanwhile, a semaphore indicated the number of free identical toilets. Say, we have four toilets with identical locks and keys. The semaphore count is then set to 4 at the beginning of the operation, as all of the four toilers are currently free. The semaphore count is decremented whenever a person comes in, or incremented if the person has come out. If all toilets are occupied, there would be no free key left and the semaphore count would be 0. If one person leaves a toilet, the semaphore count is incremented to 1, and there is one free key to be given to the next person in the queue. A binary semaphore, in this context, is if there is just one toilet available.
The Producer-Consumer Problem
Assume that we have a buffer that has a length of 4096 bytes (4 KB). Then, there is a producer thread which collects and writes data to the buffer, and a consumer thread which processes the data in the buffer. Our objective is to make these two threads to run without coming across each other.
By using a Mutex, we can create a locking mechanism on the buffer. Since a Mutex provides a mutual exclusion, only one thread can have the key and proceed with its work at a time. Only one thread can work with the entire buffer at any point of time. As long as the buffer is filled by the producer, the consumer has to wait. Vice versa, as long as the consumer fills the buffer, the producer has to wait.
Meanwhile, if it is possible to split the 4 KB buffer into four 1 KB buffers with identical resources, we can implement a semaphore instead. The consumer and producer can work on different buffers at the same time.
When to Use and Possible Problems
Keep in mind that a Mutex can only be released by the thread that has acquired it, a.k.a. the current owner. It cannot be released by the other threads. Thus, a Mutex is ideal to be used when you want to execute a critical operation, something that should not be bothered by any other thread, without the possibility for any other thread to release the lock.
Since a Mutex is a lock, it can only be in one state, either locked or unlocked. However, a recursive Mutex in a POSIX compliant system can be locked more than once while retaining just one state. If a non-recursive Mutex is locked more than once, the system will go into a deadlock. This is because, whenever a thread that has locked a Mutex tries to lock the Mutex again, the thread will go into the waiting list yet there is no other thread that can unlock the Mutex.
You can use a semaphore if you want a more ‘flexible’ way to control the access to the resource. Use this if you want a thread to sleep until another thread tells it to wake up. But a poorly implemented semaphore cannot fully guarantee that no conflict is going to happen.
|- Locking mechanism||- Signaling mechanism|
|- Can only be in one of two possible states, which are locked or unlocked||- Is set according to the arbitrary resource count|
|- Can only be released by the current owner||- Can be signaled from any thread or process|
|- Suitable for critical operations||- Suitable for synchronization problems that require signaling from any thread or process|
A Mutex is a locking mechanism. It has an ownership associated with it. Only the current owner can release the lock of a Mutex. It is an ideal solution for ensuring a critical operation. Meanwhile, a semaphore is a signaling mechanism, which is set according to the arbitrary resource count. A semaphore can be more suitable in synchronization problems where you want to be able to signal from any thread or process.