
So each thread is using the same semaphore to provide mutual exclusion for its two critical sections. The mutual exclusion is quite simple as well - m1 and m2 cannot enter the critical section at the same time. Now let's look at mutual exclusion with a binary semaphore: thread mutual_ex //constructor Thread B comes along, finishes B1, and then frees thread A - which then completes B2. Let's say thread A comes executes first - gets to sem.P(), and waits, since the counter is 0 (closed). In the above example, B2 can only execute after B1 has finished execution. Semaphore s(0) // we start the semaphore at 0 (closed) Semaphore &s //locks/semaphores are passed by reference! think about why this is so. Now, it is fairly obvious to see how binary semaphores can be used to solve synchronization and mutual exclusion - they are essentially locks. Therefore, a task gets added to the list in the P() routine if it cannot progress, and "freed" using the V() routine.

Tasks block, and add themselves to the semaphore's list only when the counter is zero. What is important to understand is that the semaphore counter keeps track of the number of tasks that do not have to block, i.e., they can make progress. A counting semaphore has multiple values for count. You can think of it as being similar to a lock with two values : open/closed. In a binary semaphore, the counter logically goes between 0 and 1. A semaphore performs two operations : wait (P), and release (V) - these are the only two operations that one can perform on a semaphore. We will see how these two types of locks (semaphores are more generally a kind of locking mechanism) help us achieve synchronization and mutual exclusion.Ī semaphore has two parts : a counter, and a list of tasks waiting to access a particular resource. There are two essential concepts to building concurrent programs - synchronization and mutual exclusion.

This would allow the X processes to access that resource at the same time yet the process X+1 would have to wait till one of the processes in the critical section gets out. The max value that a counting semaphore can take is the the number of processes you want to allow into the critical section at the same time.Īgain, you might have a case where you want exclusion over a certain resource, yet you know this resource can be accessed by a max number of processes (say X), so you set a counting semaphore with the value X. The max value X they take allows X process/threads to access the shared resource simultaneously.įor further information, take a look at this link. On the other hand, counting semaphores take more than two values, they can have any value you want. Actually, both types are used to synchronize access to a shared resource, whether the entity which is trying to access is a process or even a thread.īinary semaphores are binary, they can have two values only one to represent that a process/thread is in the critical section(code that access the shared resource) and others should wait, the other indicating the critical section is free.
