Where to use a binary semaphore with a mutex?

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

Both can have values ​​0 and 1, but the mutex can be unlocked by the same one that acquired the mutex lock. A thread that acquires a mutex lock may have a priority inversion; in case of a higher priority, the process wants to get the same mutex, whereas this is not so with the binary semaphore.

So where should I use binary semaphores? Can someone give an example?

EDITOR: I think I figured out the work of both. In principle, a binary semaphore offers synchronization, while a deadlock mechanism offers a lock mechanism. I read a few examples from the Galvin OS book to make it clearer.

+6
source share
3 answers

One typical situation is when I think binary semaphores are very useful for initializing threads, where the thread will be read from the structure belonging to the parent thread. The parent thread needs to wait for the new thread to read the general data from the structure before it can shorten the life of the structure (for example, leaving its scope). With a binary semaphore, all you have to do is initialize the semaphore value to zero and provide the child message with it while the parent waits for it. Without semaphores, you will need a mutex variable and conditions, as well as more ugly programming logic to use them.

+5
source

In almost all cases, I use a binary semaphore to signal another thread without blocking.

A simple usage example for a synchronous request:

Theme 1 :

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

Theme 2 :

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

Note. Before processing semaphore in processing stream 2, you can safely set the data in stream 1 without additional synchronization.

+3
source

A canonical example of using a counting semaphore instead of a binary mutex is when you have a limited amount of available resources: a) interchangeable and b) more than one.

For example, if you want a maximum of 10 readers to be able to access the database right away, you can use a counted semaphore initialized to 10 to restrict access to the resource. Each reader should get a semaphore before accessing the resource, reducing the available score. When the counter reaches 0 (i.e. 10 readers have access and use the database), all other readers are blocked. As soon as the reader finishes work, they reset the number of semaphores to one to indicate that they no longer use the resource, and another reader can now get the semaphore lock and access them instead.

However, the calculated semaphore, like all other synchronization primitives, has many use cases, and this is just a question outside the box. You may find that many of the problems you use to solve with a mutex plus additional logic can be more easily and more simply implemented using a semaphore. A mutex is a subset of a semaphore, i.e. Everything that you can do with a mutex can be done with a semaphore (just set the count value to one), but there are things that can only be done with a semaphore that can't be done with just a mutex.

At the end of the day, any of the synchronization primitives is usually enough to do something (think of it as a "completion-completion" for thread synchronization to strengthen this word). Nevertheless, each of them is adapted to different applications, and although you can force you to bet with some setting and additional glue, it is possible that another synchronization primitive is better suited for work.

+1
source

Source: https://habr.com/ru/post/920715/


All Articles