Operating Systems Lecture 15: Semaphores

Operating Systems Lecture 15: Semaphores

Understanding Semaphores in Thread Synchronization

Introduction to Semaphores

  • Semaphores are synchronization primitives similar to condition variables, used for signaling between threads.
  • They consist of an underlying counter that is not directly accessible to users; operations are performed through specific functions.

Functions of Semaphores

  • Two main functions:
  • Semaphore Post (Up): Increments the counter without blocking.
  • Semaphore Wait (Down): Decrements the counter and blocks the thread if the counter becomes negative.

Semaphore Behavior Explained

  • A semaphore initialized with a value of one acts as a binary semaphore or simple lock.
  • When a thread calls wait, it decrements the value; if another thread calls wait while the value is zero, it will block until released.

Parent-Child Thread Synchronization Example

  • Semaphores can enforce order between threads, such as ensuring a parent thread waits for its child.
  • If initialized with zero, calling wait on the semaphore by the parent will block until the child increments it using post.

Importance of Initial Values

  • The initial value of semaphores is crucial; incorrect initialization can lead to unintended behavior like premature unblocking.

Producer-Consumer Problem Using Semaphores

Setting Up Semaphores for Buffer Management

  • Multiple semaphores are needed:
  • One for tracking empty slots (initialized to buffer size).
  • Another for full slots (initialized to zero).
  • A mutex semaphore for protecting shared resources.

Producer and Consumer Operations

  • Producers take locks before adding items to buffers and release them afterward. Consumers do similarly when retrieving items.

Understanding Semaphore Weighting and Mutexes

The Importance of Matching Weights with Posts

  • It is crucial to match the weight of a semaphore with its corresponding post. This ensures that the up and down values of a semaphore balance each other out, allowing for proper signaling when waiting.
  • A subtle but important point is that acquiring a mutex should occur after calling weight and signal on other semaphores to avoid potential deadlocks.

Consequences of Incorrect Semaphore Handling

  • If the order of operations is reversed—calling semaphore weight before acquiring the mutex—it can lead to a situation where a thread goes to sleep while holding a lock, causing deadlock.
  • In this scenario, if the queue is full and the consumer cannot run due to being blocked by the mutex, it creates an impasse where neither producer nor consumer can proceed.

Best Practices for Semaphore Usage

  • When blocking on a semaphore, it's essential not to hold any additional locks that may be required by other threads attempting to wake you up. This practice helps prevent subtle bugs associated with semaphores.
Video description

Based on the book Operating Systems: Three Easy Pieces (http://pages.cs.wisc.edu/~remzi/OSTEP/) Note a couple of minor errors in the video: https://www.cse.iitb.ac.in/~mythili/os/errata.txt For more information please visit https://www.cse.iitb.ac.in/~mythili/os/