Semaphores in Process Synchronization

Semaphores are integer variables used to solve the critical section problem and achieve process synchronization. They help in controlling access for multiple processes to shared resources.

1. Key Concepts
  • A semaphore is a simple integer variable.

  • It can only be accessed via two atomic operations: wait() (also known as P() or down()) and signal() (also known as V() or up()).

  • The value of a semaphore cannot be negative.

2. Types of Semaphores
2.1 Binary Semaphores (Mutex Locks)
  • Can only take two values: 0 or 1.

  • Primarily used to implement mutual exclusion, ensuring only one process is in the critical section at a time.

  • wait() operation: If the semaphore value is 1, it's decremented to 0, and the process proceeds. If 0, the process waits.

  • signal() operation: Sets the semaphore value to 1, allowing another waiting process to enter.

2.2 Counting Semaphores
  • Can take any non-negative integer value.

  • Used to control access to a resource with multiple instances.

  • Initialized with the total number of available resources.

  • wait() operation: Decrements the semaphore value. If the value becomes negative, the process is blocked and waits.

  • signal() operation: Increments the semaphore value. If its value becomes non-negative or zero, it indicates that a waiting process can be unblocked (woken up).

3. Semaphore Operations
3.1 wait() Operation
  • Decrements the semaphore value. If the value becomes negative, the process is blocked and added to a waiting queue.

wait(semaphore S) {
    S.value = S.value - 1;
    if (S.value < 0) {
        add this process to S.list;
        block();
    }
}
3.2 signal() Operation
  • Increments the semaphore value. If the value is less than or equal to 0, it removes a process from the waiting queue and wakes it up.

signal(semaphore S) {
    S.value = S.value + 1;
    if (S.value <= 0) {
        remove a process P from S.list;
        wakeup(P);
    }
}
4. Advantages and Disadvantages
  • Advantages: Enforces strict mutual exclusion, more efficient than busy-waiting in blocking implementations, and provides a structured way for synchronization.

  • Disadvantages: Complex to manage, potential for deadlocks and starvation if not implemented carefully, and susceptible to programmer errors (e.g., incorrect order of wait()/signal() calls).