7
votes

While reading about binary semaphore and mutex I found the following difference:

Both can have value 0 and 1, but mutex can be unlocked by the same thread which has acquired the mutex lock. A thread which acquires mutex lock can have priority inversion in case a higher priority process wants to acquire the same mutex whereas this is not the case with binary semaphore.

So where should I use binary semaphores? Can anyone cite an example?

EDIT: I think I have figured out the working of both. Basically binary semaphore offer synchronization whereas mutex offer locking mechanism. I read some examples from Galvin OS book to make it more clear.

3

3 Answers

6
votes

One typical situation where I find binary semaphores very useful is for thread initialization where the thread will read from a structure owned by the parent thread. The parent thread needs to wait for the new thread to read the shared data from the structure before it can let the structure's lifetime end (by leaving its scope, for instance). With a binary semaphore, all you have to do is initialize the semaphore value to zero and have the child post it while the parent waits on it. Without semaphores, you'd need a mutex and condition variable and much uglier program logic for using them.

3
votes

In almost all cases I use binary semaphore to signal other thread without locking.

Simple example of usage for synchronous request:

Thread 1:

Semaphore sem;
request_to_thread2(&sem); // Function sending request to thread2 in any fashion
sem.wait();               // Waiting request complete

Thread 2:

Semaphore *sem;
process_request(sem);     // Process request from thread 1
sem->post();              // Signal thread 1 that request is completed

Note: You before post semaphore in thread 2 processing you can safely set thread 1 data without any additional synchronization.

1
votes

The canonical example for using a counted semaphore instead of a binary mutex is when you have a limited number of resources available that are a) interchangeable and b) more than one.

For instance, if you want to allow a maximum of 10 readers to access a database at once, you can use a counted semaphore initialized to 10 to limit access to the resource. Each reader must acquire the semaphore before accessing the resource, decrementing the available count. Once the count reaches 0 (i.e. 10 readers have gained access to, and are stil using the database), all other readers are locked out. Once a reader finishes, they bump semaphore count back up by one to indicate that they are no longer using the resource and some other reader may now obtain the semaphore lock and gain access in their stead.

However, the counted semaphore, just like all other synchronization primitives, has many use cases and it's just a matter of thinking outside the box. You may find that many problems you are used to solving with a mutex plus additional logic can be more-easily and more-straightforwardly implemented with a semaphore. A mutex is a subset of the semaphore, that is to say, anything you can do with a mutex can be done with a semaphore (simply set the count to one), but that there are things that can be done with a semaphore alone that cannot be done with just a mutex.

At the end of the day, any one synchronization primitive is generally enough to do anything (think of it as being "turing-complete" for thread synchronization, to bastardize that word). However, each is tailor-fit to a different application, and while you may be able to force one to do your bidding with some customization and additional glue, it is possible that a different synchronization primitive is better-fit for the job.