Binary Semaphore as resource access controller: Multithreading POSIX - multithreading

As per multithreading concepts, I have learned so far:
MUTEX: A mutex_t object can be used for managing access to a resource.
BINARY SEMAPHORE: A sem_t object can also be used to manage access to a resource
Differenrce between two: The concept of ownership i.e. in case of mutex_t the thread which locked the mutex_t, only it can unlock it. But in case of sem_t, there is no concpt of ownership and hence any thread can perform sem_post() on the sem_t object. This is the reson it can be used as Event signals.
Now suppose my crital section appears as:
A) Using mutex_t
typedef struct {
int count;
pthread_mutex_t mutex;
}counter;
counter count;
void increment(counter* c)
{
pthread_mutex_lock(&(c->mutex));
(c->count)++;
pthread_mutex_unlock(&(c->mutex));
}
B) Using sem_t
EDIT: (Binary semaphore i.e. initialized to 1)
typedef struct {
int count;
sem_t sem;
}counter;
counter count;
void increment(counter* c)
{
sem_wait(&(c->sem));
(c->count)++;
sem_post(&(c->sem));
}
In case of B) till the time sem is zero no thread can enter the critical section and hence providing access control. But suppose due to some event sem_post() is executed by some other thread then it will allow access to critical section by other threads.
In this case this is actually a buggy situation and not a proper a access control.And hence programmer has to be careful with use of binary semaphore for resource access control.
I can conclude, it always better to use mutex_t for access control and binary semaphore for event signalling.
Please let me know if my understanding is correct or am I missing something?

Mutexes are very specific in their purpose. Like you said, they can only ever be released by the thread currently holding the mutex, and they only allow single entrancy. A mutex is effectively a semaphore initialized to a count of 1 that also verifies that the thread calling post is the thread that last called wait ('ownership' invariance).
Your example does not show the initalization conditions for your semaphore. If you wanted to use it in the same way as a mutex, it would have to be initialized to a count of 1.
Semaphores do have a wide range of uses, so I wouldn't call them 'unsafe'. For example, lets say that you have some resource that allows, say, 5 total consumers to be running. So you would protect that resource with a semaphore initialized to 5. As consumers invoke the resource, the semaphore will tick down until it hits zero, at which point it'll block new consumers until running consumers increment the semaphore. This is called a counting semaphore.
A great example of how to use a counting semaphore is a blocking queue - a simple Queue that has an Enqueue and a Dequeue method. Each Enqueue increments the semaphore, and each Dequeue decrements the semaphore. In this way, if the queue is empty, Dequeuers will be blocked.
Another example of how a semaphore could be used would be in a simple signaling situation, as you mention:
Thread A enqueues 10 jobs into a thread pool to run them in parallel. Each job has a semaphore associated with it that is initially set to 0. When the job has been completed by the thread pool, the thread pool posts to the jobs semaphore. Meanwhile, Thread A is waiting on each job's semaphore to find out when they complete.
So we see many uses for a semaphore:
Making Mutexs, where the initial count = 1
Protecting limited resources, where the initial count = N, the limit
Counting queued work, where the initial count is = 0 and grows with queued work
Signaling job completion, where the initial count = 0, and the semaphore is used to coordinate two threads.
I would remind you that locking in general is a topic that requires close attention - in systems that have complex interactions, its sometimes very easy to use too little locking, causing unintended concurrency, or too much locking, causing deadlocks.

Related

Why a guard exists in this implementation of a lock?

Here in this video at 26:00, there is an implementation of a lock that tries to avoids busy waiting as much as possible by using a wait queue, the code looks like this (pseudo code):
int guard = 0;
int value = FREE;
Acquire()
{
while (test_and_set(guard));
if (value == BUSY) {
release_guard_and_wait();
} else {
value = BUSY;
guard = 0;
}
}
Release()
{
while (test_and_set(guard));
if (!wait_queue.empty())
wake_one();
else
value = FREE;
guard = 0;
}
test_and_set is an atomic operation that returns the old value of guard and sets it to 1.
release_guard_and_wait has to be atomic as well to avoid potential problems:
If the thread waits then releases the guard when it wakes up, no thread will be able to acquire it.
If the thread releases the guard then waits, this scenario might happen:
thread 1 (in Acquire) -> guard = 0;
thread 2 (in Release) -> test_and_set(guard);
thread 2 (in Release) -> wake_one();
thread 1 (in Acquire) -> wait();
thread 2 (in Release) -> guard = 0;
wake_one wakes one thread (takes it from the wait queue and puts it in the ready queue).
My question is, why using guard? isn't this redundant?
The code without guard may look like this:
int value = 0;
Acquire()
{
while (test_and_set(value))
wait();
}
Release()
{
value = 0;
wake_one();
}
Will these two implementations behave differently under some conditions? Is there any advantage in using the guard?
There are two big problems with your code.
First, your code has a race condition. Consider:
Thread 1 holds the lock, it calls Release.
Thread 2 wants the lock, it calls Acquire.
Thread 1 sets value to zero.
Thread 2 passes the test_and_set.
Thread 1 calls wake_one, it doesn't do anything.
Thread 2 calls wait, it is waiting for a wakeup that already happened.
Oops, deadlock. This is why you need an atomic release_guard_and_wait function.
Second problem:
If two threads call Acquire at the same time, your code will only cause one of them to wait. The other one will do horrible things, for example it will:
Keep a core busy, preventing other cores from reaching their peak speeds on many CPUs with adaptive clock speeds.
Waste power.
Starve another thread running in the same core on CPUs with hyperthreading and similar technologies.
When the spinning thread finally does pass the test_and_set loop, it will take a massive mispredicted branch penalty. So if several threads are waiting, each one will stall just as it gets the lock. Yuck.
On some CPUs, a test_and_set loop will cause inter-core traffic even if the comparison fails. So you may saturate inter-core buses, slowing other innocent threads (and the one holding the lock) to a crawl.
And so on.
I hate to see the test and set loop in the original code (that's only appropriate in toy code, even for very short times) but at least it won't spin for the whole time another thread holds the lock as yours will.
"there is an implementation of a lock that avoids busy waiting by using a wait channel" -- I could still see a busy waiting, in the form of this while (test_and_set(guard));). But the essence of the code is making that busy wait for a short period. All your code does is this:
Declare a lock-queue where a process can register itself for a lock.
Add the process to that lock-queue, which is interested in acquiring the lock.
Release one process from the lock-queue, when an already holding process releases the lock.
Acquire()
while (test_and_set(guard)); -- Get the gaurd for editing the lock-queue.
if (value == BUSY) {release_guard_and_wait();} -- If the lock is already acquired, add yourself to the lock-queue, and release the guard on lock-queue so that other processes may add themselves to the lock-queue. And wait till you are given a call to wake up.
else { value = BUSY; guard = 0;} -- If no process acquired the lock, then acquire by yourself and release the guard on the lock-queue.
Release()
while (test_and_set(guard)); -- Get the gaurd for editing the lock-queue.
if (!wait_queue.empty()) wake_one(); -- If the lock queue is not empty then wake one process.
else value = FREE; -- If no process is waiting for the lock in the lock-queue, just release the lock.
guard = 0; -- Of course at the end, release the guard on the lock-queue, so other processes can edit the queue.
Now coming to your modified code, you can immediately find that two processes running acquire() and release() may edit the queue at the same instant. Moreover, multiple processes trying to acquire the lock at the same time, may also corrupt the lock-queue and leave it in a broken state.

Can two wait operations executed by two separate threads on different semaphores be interleaved during execution?

I'm motivated with this citation from "Concepts in Programming Languages" by John C. Mitchell:
"Atomicity prevents individual statements of one wait procedure from being
interleaved with individual statements of another wait on the same semaphore."
Wait and signal operations need to be atomic which is often enforced by some "lower" level mechanism of acquiring lock - disabling interrupts, disabling preemption, test and set ... But, conceptually, how these locks can be in some way "private" for each semaphore instance?
In other words, is it allowed for example that one thread acquires lock at the beginning and later be preempted in the middle of executing wait operation on one semaphore, and after that another thread acquires lock at the beginning of wait operation on some other semaphore and enters in the body of its wait operation, so that two thread are in the wait operations on different semaphores at the same time? Or, shortly, whether the wait operations on two different semaphores mutually exclusive?
My point is, if thread acquires lock in wait operation on one semaphore s1, is it allowed for another thread to acquire lock at the same time in wait operation on another semaphore s2? I'm emphasizing that these are two different semaphore instances, not the same one.
For example:
class Semaphore {
...
public:
void wait();
...
}
void Semaphore::wait(){
lock();
//POINT OF CONTINUATION FOR THREAD 2!//
if(--val<0){
//POINT OF PREEMPTION FOR THREAD 1!//
block();
}
unlock();
}
Semaphore s1;
Semaphore s2:
...
So...
Is it allowed at some point of execution that one thread be preempted while executing wait operation on semaphore s1 at //POINT OF PREEMPTION FOR THREAD 1!// , and control transfers to another thread which executes wait operation of semaphore s2 at //POINT OF CONTINUATION FOR THREAD 2!//...
...or...
Is it allowed for instructions of wait operation from one semaphore to be interleaved with instruction of wait operation from another semaphore?
..or...
Is it allowed for more than one threads to be in wait operations on different semaphores at the same time?
Sorry for my wordiness but I really struggle to clarify my question. Thanks in advance.
Yes, it's allowed. One of the reasons you would use two different locks, rather than using the same lock for everything, is to avoid unnecessary dependencies like this.
Is it allowed for instructions of wait operation from one semaphore to be interleaved with instruction of wait operation from another semaphore?
Absolutely.
Is it allowed for more than one threads to be in wait operations on different semaphores at the same time?
Absolutely.
Prohibiting any of these things would hurt performance significantly for no benefit. Contention is the enemy of multi-threaded performance.

The usage case of counting semaphore

To be clear: I do mostly embedded stuff, i.e. it's C and some kind of real-time kernel in microcontroller; but actually this question should be platform-independent.
I've read nice article by Michael Barr: Mutexes and Semaphores Demystified, as well as this related answer on StackOverflow. I understand clearly what binary semaphore is for, and what mutex is for. That's great.
But to be honest I never knew, and still can't understand, what so-called counting semaphore (i.e. semaphore with max count > 1) is for. In what cases should I use it?
Long time ago, before I've read aforementioned article by Michael Barr, I've told something like "you can use it when you have, like, a hotel room with certain number of beds. The number of beds is a maximum count for the semaphore, just like a number of keys for that room".
It probably sounds nicely, but actually I never had such a situation in my programming practice (and can't imagine any), and Michael Barr said this approach is just wrong, and he seems right.
Then, after I've read the article, I supposed it might probably be used when I have, say, some kind of FIFO buffer. Assume the buffer's capacity is 10 elements, and we have two tasks: A (the producer), and B (the consumer). Then:
Semaphore's max count should be set to 10;
When A wants to put data into buffer, it signals the semaphore.
When B wants to get the data from buffer, it waits the semaphore.
Well, but it doesn't work:
What if A tries to put new data to the FIFO, but there is no room? How would it wait for the place: should it call signal before putting new data (and signal then should be able to wait until max count < max count)? If so, semaphore will be signaled before data is actually put in the FIFO, this is wrong.
Semaphore is not enough for the proper synchronization: the FIFO itself needs to be synchronized as well. And then, it produces classic TOCTTOU problem: there is a period of time while semaphore is already either signaled or waited, but FIFO isn't yet modified.
So, when should I use that beast, the counting semaphore?
The 'classic' example is, indeed, a producer-consumer queue.
An unbounded queue requires one semaphore, (to count the queue entries), and a mutex-protected thread-safe queue, (or equivalent lock-free thread-safe queue). The semaphore is intialized to zero. Producers lock the mutex, push an object onto the queue, unlock the mutex and signal the semaphore. Consumers wait on the semaphore, lock the mutex, pop the object and unlock the mutex.
An bounded queue requires two semaphores, (one 'count' to count the entries, the other 'available' to count the free space), and a mutex-protected thread-safe queue, (or equivalent lock-free thread-safe queue). 'count' is initialized to zero and 'available' to the number of spaces free in an empty queue. Producers wait for 'available', lock the mutex, push an object onto the queue, unlock the mutex and signal 'count'. Consumers wait on 'count', lock the mutex, pop the object, unlock the mutex and signal 'available'.
This is a classic use for semaphores and had been around since forever, (well, since Dijkstra, anyway:). It's been tried billions of times, and it works fine for any number of producers/consumers.
There is no TOCTTOU issue, no corner-cases, no races.
The 'mutex' functionality may be provided by yet another semaphore, initialized to 1. This allows 'two semaphore' unbounded, and 'three semaphore' bounded implementations.
I supposed it might probably be used when I have, say, some kind of FIFO buffer. Assume the buffer's capacity is 10 elements, and we have two tasks: A (the producer), and B (the consumer). Then:
Semaphore's max count should be set to 10;
When A wants to put data into buffer, it signals the semaphore.
When B wants to get the data from buffer, it waits the semaphore.
This is not the way semaphores are used in the producer-consumer scenario. The standard solution is to use two counting semaphores, one for the empty slots (initialized to the number of available slots), and another for the filled slots (initialized to 0).
Producers try to allocate empty slots to put items in, so they start with wait-ing on the semaphore assigned to the empty slots. Consumers try to "allocate" (get hold of) filled slots, so they start with wait-ing on the semaphore assigned to the filled slots.
After finishing their work, they both signal the other semaphore since they transform slots from empty to filled and from filled to empty, respectively.
Standard solution scheme:
semaphore mutex = 1;
semaphore filled = 0;
semaphore empty = SIZE;
producer() {
while ( true) {
item = produceItem();
wait(empty);
wait(mutex);
putItemIntoBuffer( item);
signal(mutex);
signal(filled);
}
}
consumer() {
while ( true) {
wait( filled);
wait( mutex);
item = removeItemFromBuffer();
signal( mutex);
signal( empty);
consumeItem( item);
}
}
I think counting semaphores serve well in this situation.
Another, maybe simpler, example could be using a counting semaphore for avoiding deadlock in the Dining philosophers scenario. Since deadlock can occur only when all philosophers sit down simultaneously and pick their (say) left fork, deadlock can be avoided by not allowing all of them into the dining room at the same time. This can be achieved by a counting semaphore (enter) initialized to one less than the number of philosophers.
The protocol of one philosopher then becomes:
wait( enter)
wait( left_fork)
wait( right_fork)
eat()
signal( left_fork)
signal( right_fork)
signal( enter)
This ensures that all philosophers cannot be in the dining room at the same time.
Some of the more popular use cases of counting semaphores are -
Limiting the number of connections in a JDBC connection pool.
Network connection throttling.
Limiting concurrent access to resources such as a disk.

Semaphore vs. Monitors - what's the difference?

What are the major differences between a Monitor and a Semaphore?
A Monitor is an object designed to be accessed from multiple threads. The member functions or methods of a monitor object will enforce mutual exclusion, so only one thread may be performing any action on the object at a given time. If one thread is currently executing a member function of the object then any other thread that tries to call a member function of that object will have to wait until the first has finished.
A Semaphore is a lower-level object. You might well use a semaphore to implement a monitor. A semaphore essentially is just a counter. When the counter is positive, if a thread tries to acquire the semaphore then it is allowed, and the counter is decremented. When a thread is done then it releases the semaphore, and increments the counter.
If the counter is already zero when a thread tries to acquire the semaphore then it has to wait until another thread releases the semaphore. If multiple threads are waiting when a thread releases a semaphore then one of them gets it. The thread that releases a semaphore need not be the same thread that acquired it.
A monitor is like a public toilet. Only one person can enter at a time. They lock the door to prevent anyone else coming in, do their stuff, and then unlock it when they leave.
A semaphore is like a bike hire place. They have a certain number of bikes. If you try and hire a bike and they have one free then you can take it, otherwise you must wait. When someone returns their bike then someone else can take it. If you have a bike then you can give it to someone else to return --- the bike hire place doesn't care who returns it, as long as they get their bike back.
Following explanation actually explains how wait() and signal() of monitor differ from P and V of semaphore.
The wait() and signal() operations on condition variables in a monitor are similar to P and V operations on counting semaphores.
A wait statement can block a process's execution, while a signal statement can cause another process to be unblocked. However, there are some differences between them. When a process executes a P operation, it does not necessarily block that process because the counting semaphore may be greater than zero. In contrast, when a wait statement is executed, it always blocks the process. When a task executes a V operation on a semaphore, it either unblocks a task waiting on that semaphore or increments the semaphore counter if there is no task to unlock. On the other hand, if a process executes a signal statement when there is no other process to unblock, there is no effect on the condition variable. Another difference between semaphores and monitors is that users awaken by a V operation can resume execution without delay. Contrarily, users awaken by a signal operation are restarted only when the monitor is unlocked. In addition, a monitor solution is more structured than the one with semaphores because the data and procedures are encapsulated in a single module and that the mutual exclusion is provided automatically by the implementation.
Link: here for further reading. Hope it helps.
Semaphore allows multiple threads (up to a set number) to access a shared object. Monitors allow mutually exclusive access to a shared object.
Monitor
Semaphore
One Line Answer:
Monitor: controls only ONE thread at a time can execute in the monitor. (need to acquire lock to execute the single thread)
Semaphore: a lock that protects a shared resource. (need to acquire the lock to access resource)
A semaphore is a signaling mechanism used to coordinate between threads. Example: One thread is downloading files from the internet and another thread is analyzing the files. This is a classic producer/consumer scenario. The producer calls signal() on the semaphore when a file is downloaded. The consumer calls wait() on the same semaphore in order to be blocked until the signal indicates a file is ready. If the semaphore is already signaled when the consumer calls wait, the call does not block. Multiple threads can wait on a semaphore, but each signal will only unblock a single thread.
A counting semaphore keeps track of the number of signals. E.g. if the producer signals three times in a row, wait() can be called three times without blocking. A binary semaphore does not count but just have the "waiting" and "signalled" states.
A mutex (mutual exclusion lock) is a lock which is owned by a single thread. Only the thread which have acquired the lock can realease it again. Other threads which try to acquire the lock will be blocked until the current owner thread releases it. A mutex lock does not in itself lock anything - it is really just a flag. But code can check for ownership of a mutex lock to ensure that only one thread at a time can access some object or resource.
A monitor is a higher-level construct which uses an underlying mutex lock to ensure thread-safe access to some object. Unfortunately the word "monitor" is used in a few different meanings depending on context and platform and context, but in Java for example, a monitor is a mutex lock which is implicitly associated with an object, and which can be invoked with the synchronized keyword. The synchronized keyword can be applied to a class, method or block and ensures only one thread can execute the code at a time.
Semaphore :
Using a counter or flag to control access some shared resources in a concurrent system, implies use of Semaphore.
Example:
A counter to allow only 50 Passengers to acquire the 50 seats (Shared resource) of any Theatre/Bus/Train/Fun ride/Classroom. And to allow a new Passenger only if someone vacates a seat.
A binary flag indicating the free/occupied status of any Bathroom.
Traffic lights are good example of flags. They control flow by regulating passage of vehicles on Roads (Shared resource)
Flags only reveal the current state of Resource, no count or any other information on the waiting or running objects on the resource.
Monitor :
A Monitor synchronizes access to an Object by communicating with threads interested in the object, asking them to acquire access or wait for some condition to become true.
Example:
A Father may acts as a monitor for her daughter, allowing her to date only one guy at a time.
A school teacher using baton to allow only one child to speak in the class.
Lastly a technical one, transactions (via threads) on an Account object synchronized to maintain integrity.
When a semaphore is used to guard a critical region, there is no direct relationship between the semaphore and the data being protected. This is part of the reason why semaphores may be dispersed around the code, and why it is easy to forget to call wait or notify, in which case the result will be, respectively, to violate mutual exclusion or to lock the resource permanently.
In contrast, niehter of these bad things can happen with a monitor. A monitor is tired directly to the data (it encapsulates the data) and, because the monitor operations are atomic actions, it is impossible to write code that can access the data without calling the entry protocol. The exit protocol is called automatically when the monitor operation is completed.
A monitor has a built-in mechanism for condition synchronisation in the form of condition variable before proceeding. If the condition is not satisfied, the process has to wait until it is notified of a change in the condition. When a process is waiting for condition synchronisation, the monitor implementation takes care of the mutual exclusion issue, and allows another process to gain access to the monitor.
Taken from The Open University M362 Unit 3 "Interacting process" course material.

When should we use mutex and when should we use semaphore

When should we use mutex and when should we use semaphore ?
Here is how I remember when to use what -
Semaphore:
Use a semaphore when you (thread) want to sleep till some other thread tells you to wake up. Semaphore 'down' happens in one thread (producer) and semaphore 'up' (for same semaphore) happens in another thread (consumer)
e.g.: In producer-consumer problem, producer wants to sleep till at least one buffer slot is empty - only the consumer thread can tell when a buffer slot is empty.
Mutex:
Use a mutex when you (thread) want to execute code that should not be executed by any other thread at the same time. Mutex 'down' happens in one thread and mutex 'up' must happen in the same thread later on.
e.g.: If you are deleting a node from a global linked list, you do not want another thread to muck around with pointers while you are deleting the node. When you acquire a mutex and are busy deleting a node, if another thread tries to acquire the same mutex, it will be put to sleep till you release the mutex.
Spinlock:
Use a spinlock when you really want to use a mutex but your thread is not allowed to sleep.
e.g.: An interrupt handler within OS kernel must never sleep. If it does the system will freeze / crash. If you need to insert a node to globally shared linked list from the interrupt handler, acquire a spinlock - insert node - release spinlock.
A mutex is a mutual exclusion object, similar to a semaphore but that only allows one locker at a time and whose ownership restrictions may be more stringent than a semaphore.
It can be thought of as equivalent to a normal counting semaphore (with a count of one) and the requirement that it can only be released by the same thread that locked it(a).
A semaphore, on the other hand, has an arbitrary count and can be locked by that many lockers concurrently. And it may not have a requirement that it be released by the same thread that claimed it (but, if not, you have to carefully track who currently has responsibility for it, much like allocated memory).
So, if you have a number of instances of a resource (say three tape drives), you could use a semaphore with a count of 3. Note that this doesn't tell you which of those tape drives you have, just that you have a certain number.
Also with semaphores, it's possible for a single locker to lock multiple instances of a resource, such as for a tape-to-tape copy. If you have one resource (say a memory location that you don't want to corrupt), a mutex is more suitable.
Equivalent operations are:
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
Aside: in case you've ever wondered at the bizarre letters (P and V) used for claiming and releasing semaphores, it's because the inventor was Dutch. In that language:
Probeer te verlagen: means to try to lower;
Verhogen: means to increase.
(a) ... or it can be thought of as something totally distinct from a semaphore, which may be safer given their almost-always-different uses.
It is very important to understand that a mutex is not a semaphore with count 1!
This is the reason there are things like binary semaphores (which are really semaphores with count 1).
The difference between a Mutex and a Binary-Semaphore is the principle of ownership:
A mutex is acquired by a task and therefore must also be released by the same task.
This makes it possible to fix several problems with binary semaphores (Accidental release, recursive deadlock, and priority inversion).
Caveat: I wrote "makes it possible", if and how these problems are fixed is up to the OS implementation.
Because the mutex has to be released by the same task it is not very good for the synchronization of tasks. But if combined with condition variables you get very powerful building blocks for building all kinds of IPC primitives.
So my recommendation is: if you got cleanly implemented mutexes and condition variables (like with POSIX pthreads) use these.
Use semaphores only if they fit exactly to the problem you are trying to solve, don't try to build other primitives (e.g. rw-locks out of semaphores, use mutexes and condition variables for these)
There is a lot of misunderstanding between mutexes and semaphores. The best explanation I found so far is in this 3-Part article:
Mutex vs. Semaphores – Part 1: Semaphores
Mutex vs. Semaphores – Part 2: The Mutex
Mutex vs. Semaphores – Part 3 (final part): Mutual Exclusion Problems
While #opaxdiablo answer is totally correct I would like to point out that the usage scenario of both things is quite different. The mutex is used for protecting parts of code from running concurrently, semaphores are used for one thread to signal another thread to run.
/* Task 1 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing);
/* Task 2 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex
The semaphore scenario is different:
/* Task 1 - Producer */
sema_post(&sem); // Send the signal
/* Task 2 - Consumer */
sema_wait(&sem); // Wait for signal
See http://www.netrino.com/node/202 for further explanations
See "The Toilet Example" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm:
Mutex:
Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue.
Officially: "Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section."
Ref: Symbian Developer Library
(A mutex is really a semaphore with value 1.)
Semaphore:
Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.
Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)."
Ref: Symbian Developer Library
Mutex is to protect the shared resource.
Semaphore is to dispatch the threads.
Mutex:
Imagine that there are some tickets to sell. We can simulate a case where many people buy the tickets at the same time: each person is a thread to buy tickets. Obviously we need to use the mutex to protect the tickets because it is the shared resource.
Semaphore:
Imagine that we need to do a calculation as below:
c = a + b;
Also, we need a function geta() to calculate a, a function getb() to calculate b and a function getc() to do the calculation c = a + b.
Obviously, we can't do the c = a + b unless geta() and getb() have been finished.
If the three functions are three threads, we need to dispatch the three threads.
int a, b, c;
void geta()
{
a = calculatea();
semaphore_increase();
}
void getb()
{
b = calculateb();
semaphore_increase();
}
void getc()
{
semaphore_decrease();
semaphore_decrease();
c = a + b;
}
t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);
With the help of the semaphore, the code above can make sure that t3 won't do its job untill t1 and t2 have done their jobs.
In a word, semaphore is to make threads execute as a logicial order whereas mutex is to protect shared resource.
So they are NOT the same thing even if some people always say that mutex is a special semaphore with the initial value 1. You can say like this too but please notice that they are used in different cases. Don't replace one by the other even if you can do that.
Trying not to sound zany, but can't help myself.
Your question should be what is the difference between mutex and semaphores ?
And to be more precise question should be, 'what is the relationship between mutex and semaphores ?'
(I would have added that question but I'm hundred % sure some overzealous moderator would close it as duplicate without understanding difference between difference and relationship.)
In object terminology we can observe that :
observation.1 Semaphore contains mutex
observation.2 Mutex is not semaphore and semaphore is not mutex.
There are some semaphores that will act as if they are mutex, called binary semaphores, but they are freaking NOT mutex.
There is a special ingredient called Signalling (posix uses condition_variable for that name), required to make a Semaphore out of mutex.
Think of it as a notification-source. If two or more threads are subscribed to same notification-source, then it is possible to send them message to either ONE or to ALL, to wakeup.
There could be one or more counters associated with semaphores, which are guarded by mutex. The simple most scenario for semaphore, there is a single counter which can be either 0 or 1.
This is where confusion pours in like monsoon rain.
A semaphore with a counter that can be 0 or 1 is NOT mutex.
Mutex has two states (0,1) and one ownership(task).
Semaphore has a mutex, some counters and a condition variable.
Now, use your imagination, and every combination of usage of counter and when to signal can make one kind-of-Semaphore.
Single counter with value 0 or 1 and signaling when value goes to 1 AND then unlocks one of the guy waiting on the signal == Binary semaphore
Single counter with value 0 to N and signaling when value goes to less than N, and locks/waits when values is N == Counting semaphore
Single counter with value 0 to N and signaling when value goes to N, and locks/waits when values is less than N == Barrier semaphore (well if they dont call it, then they should.)
Now to your question, when to use what. (OR rather correct question version.3 when to use mutex and when to use binary-semaphore, since there is no comparison to non-binary-semaphore.)
Use mutex when
1. you want a customized behavior, that is not provided by binary semaphore, such are spin-lock or fast-lock or recursive-locks.
You can usually customize mutexes with attributes, but customizing semaphore is nothing but writing new semaphore.
2. you want lightweight OR faster primitive
Use semaphores, when what you want is exactly provided by it.
If you dont understand what is being provided by your implementation of binary-semaphore, then IMHO, use mutex.
And lastly read a book rather than relying just on SO.
I think the question should be the difference between mutex and binary semaphore.
Mutex = It is a ownership lock mechanism, only the thread who acquire the lock can release the lock.
binary Semaphore = It is more of a signal mechanism, any other higher priority thread if want can signal and take the lock.
All the above answers are of good quality,but this one's just to memorize.The name Mutex is derived from Mutually Exclusive hence you are motivated to think of a mutex lock as Mutual Exclusion between two as in only one at a time,and if I possessed it you can have it only after I release it.On the other hand such case doesn't exist for Semaphore is just like a traffic signal(which the word Semaphore also means).
As was pointed out, a semaphore with a count of one is the same thing as a 'binary' semaphore which is the same thing as a mutex.
The main things I've seen semaphores with a count greater than one used for is producer/consumer situations in which you have a queue of a certain fixed size.
You have two semaphores then. The first semaphore is initially set to be the number of items in the queue and the second semaphore is set to 0. The producer does a P operation on the first semaphore, adds to the queue. and does a V operation on the second. The consumer does a P operation on the second semaphore, removes from the queue, and then does a V operation on the first.
In this way the producer is blocked whenever it fills the queue, and the consumer is blocked whenever the queue is empty.
A mutex is a special case of a semaphore. A semaphore allows several threads to go into the critical section. When creating a semaphore you define how may threads are allowed in the critical section. Of course your code must be able to handle several accesses to this critical section.
I find the answer of #Peer Stritzinger the correct one.
I wanted to add to his answer the following quote from the book Programming with POSIX Threads by David R Butenhof. On page 52 of chapter 3 the author writes (emphasis mine):
You cannot lock a mutex when the calling thread already has that mutex locked. The result of attempting to do so may be an error return (EDEADLK), or it may be a self-deadlock, where the unfortunate thread waits forever. You cannot unlock a mutex that is unlocked, or that is locked by another thread. Locked mutexes are owned by the thread that locks them. If you need an "unowned" lock, use a semaphore. Section 6.6.6 discusses semaphores)
With this in mind, the following piece of code illustrates the danger of using a semaphore of size 1 as a replacement for a mutex.
sem = Semaphore(1)
counter = 0 // shared variable
----
Thread 1
for (i in 1..100):
sem.lock()
++counter
sem.unlock()
----
Thread 2
for (i in 1..100):
sem.lock()
++counter
sem.unlock()
----
Thread 3
sem.unlock()
thread.sleep(1.sec)
sem.lock()
If only for threads 1 and 2, the final value of counter should be 200. However, if by mistake that semaphore reference was leaked to another thread and called unlock, than you wouldn't get mutual exclusion.
With a mutex, this behaviour would be impossible by definition.
Binary semaphore and Mutex are different. From OS perspective, a binary semaphore and counting semaphore are implemented in the same way and a binary semaphore can have a value 0 or 1.
Mutex -> Can only be used for one and only purpose of mutual exclusion for a critical section of code.
Semaphore -> Can be used to solve variety of problems. A binary semaphore can be used for signalling and also solve mutual exclusion problem. When initialized to 0, it solves signalling problem and when initialized to 1, it solves mutual exclusion problem.
When the number of resources are more and needs to be synchronized, we can use counting semaphore.
In my blog, I have discussed these topics in detail.
https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html

Resources