1. The Evolution of Synchronization

Semaphores are powerful but dangerous. A single missing V() call can freeze the entire system. Monitors were invented to make synchronization safer and more structured.

What is a Monitor?

A Monitor is a synchronization construct that enforces:

  1. Mutual Exclusion: Only one thread can be active inside the monitor at a time.
  2. Encapsulation: Shared data is hidden and only accessible via monitor procedures.

In Java, every Object is a Monitor (via synchronized).

Condition Variables

Monitors use Condition Variables to allow threads to wait for a specific state (e.g., “Buffer Not Empty”).

  • Wait(): Release the lock and go to sleep in the Wait Set.
  • Signal() / Notify(): Wake up one thread from the Wait Set and move it to the Entry Set.

[!IMPORTANT] Always use while loops! When a thread wakes up, the condition might have changed again (MESA semantics). while (buffer.isEmpty()) { wait(); }


2. Interactive: Monitor Lifecycle

Visualize the journey of a thread through a Monitor.

  1. Entry Set: Waiting to acquire the lock.
  2. Owner: Executing inside the monitor.
  3. Wait Set: Waiting for a condition (released lock).
Entry Set (Queue)
Monitor (Owner)
Wait Set (CV)
System Empty.

3. Go Channels: CSP

Go takes a different approach based on CSP (Communicating Sequential Processes). Instead of locking shared memory, goroutines share data by sending it through Channels.

“Do not communicate by sharing memory; instead, share memory by communicating.”

Unbuffered vs Buffered

  • Unbuffered: Synchronous. Sender blocks until Receiver is ready. Handshake.
  • Buffered: Asynchronous (up to capacity). Sender only blocks if buffer is full.

4. Code Example: Monitors vs Channels

Java
Go
```java class MessageQueue { private String message; private boolean empty = true; public synchronized String take() throws InterruptedException { while (empty) { wait(); // Wait for message } empty = true; notifyAll(); return message; } public synchronized void put(String message) throws InterruptedException { while (!empty) { wait(); // Wait for empty slot } this.message = message; empty = false; notifyAll(); } } ```
```go package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ping" // Blocks until received }() msg := <-messages // Blocks until sent fmt.Println(msg) } ```