CodeMaster
Article ID: 2506
operating-system
3 min read
Semaphores and Its types

Semaphores are synchronisation primitives used to manage concurrent processes by controlling access to shared resources in a computing environment. They are essential for preventing race conditions...

CS Core
October 11, 2024
Tutorial Article

Semaphores are synchronisation primitives used to manage concurrent processes by controlling access to shared resources in a computing environment. They are essential for preventing race conditions, where multiple processes attempt to access and modify shared data simultaneously, leading to unpredictable outcomes.

Semaphores Concept

A semaphore is essentially a variable that signals whether a particular resource is available. Using operations like wait (or P) and signal (or V), semaphores coordinate the activities of different processes, ensuring that only a specified number of processes can access the critical section at any given time. This coordination is crucial in multi-threaded applications to maintain data consistency and integrity.

Binary Semaphores and Counting Semaphores

Binary Semaphores

Binary semaphores, also known as mutexes (mutual exclusion), have only two states: 0 and 1. They ensure that a resource is accessed by only one thread at a time. When a thread acquires the semaphore, it sets the value to 0, and when it releases the semaphore, it sets the value back to 1.

Binary Semaphore

Binary semaphores are typically used for simple lock/unlock mechanisms where mutual exclusion is required.

Counting Semaphores

Counting semaphores can take on any non-negative integer value and are used to control access to a resource with a limited number of instances. The semaphore's value is initialised to the number of available resources. Each wait operation decrements the value, and each signal operation increments it. If the value is zero, indicating no resources are available, the process attempting to decrement the semaphore is blocked until another process increments it.

Counting Semaphore

This type of semaphore is useful in scenarios where a pool of identical resources needs to be managed, such as a fixed number of database connections.

Semaphores Vs Other Synchronisation Primitives

Semaphores are often compared with other synchronisation primitives like locks, monitors, and condition variables:

  • Unlike locks, which are used for mutual exclusion, semaphores offer more versatility with their counting capability, allowing multiple instances of a resource to be managed.
  • Monitors encapsulate both mutual exclusion and the condition variables needed for complex waiting scenarios, offering a higher level of abstraction compared to semaphores.
  • Condition variables, used with locks, allow threads to wait for certain conditions to be met, sometimes making them easier to use than semaphores.

However, semaphores provide a simpler and more direct way to implement certain synchronisation scenarios, especially those involving limited resource pools.

Deadlock Avoidance

Deadlocks occur when two or more processes wait indefinitely for resources held by each other. To avoid deadlocks with semaphores, techniques such as resource ordering, timeout mechanisms, and deadlock detection algorithms can be employed. Ensuring that all semaphores are requested in a predefined global order can prevent circular wait conditions, a key factor in deadlock.

Deadlock Avoidance

Priority Inversion

Priority inversion happens when a higher-priority task is waiting for a resource held by a lower-priority task, causing the higher-priority task to be indirectly preempted. This can be mitigated using priority inheritance protocols, where a lower-priority task temporarily inherits the higher priority of the blocked task, ensuring that critical sections are exited more quickly.

Special thanks to Gauri Tomar for contributing to this article on takeUforward. If you also wish to share your knowledge with the takeUforward fam, please check out this article.