Lesson Completion
Back to course

Semaphore and Synchronization Utilities: Thread Coordination

Advanced
25 minutes4.6Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Synchronization utilities coordinate threads beyond basic locks. Semaphore controls access to limited resources (n permits). CountDownLatch makes threads wait until count reaches zero (one-time barrier). CyclicBarrier makes threads wait for each other at barrier (reusable). Phaser is flexible multi-phase synchronizer.
  • Common use cases: connection pools (Semaphore), startup coordination (CountDownLatch), parallel algorithms (CyclicBarrier), multi-stage workflows (Phaser).

Think of parking lot. Semaphore = 50 parking spots (limited permits). CountDownLatch = race start (wait until all runners ready). CyclicBarrier = group photo (wait until everyone arrives). Phaser = multi-stage tournament!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Semaphore: Restaurant with 10 tables (10 permits)—wait if full
  • CountDownLatch: Countdown timer (3...2...1...GO!)—one-time use
  • CyclicBarrier: Group tour (everyone waits at checkpoint)—reusable
  • Phaser: Multi-round tournament (phase 1, then phase 2, ...)

3. Technical Mastery (The "Deep Dive")

Semaphore (Resource Pooling)

java
Semaphore semaphore = new Semaphore(3); // 3 permits semaphore.acquire(); // Get permit (blocks if none available) try { // Use resource } finally { semaphore.release(); // Return permit }

CountDownLatch (One-Time Barrier)

java
CountDownLatch latch = new CountDownLatch(3); // Wait for 3 events // Worker threads latch.countDown(); // Decrement count // Main thread latch.await(); // Blocks until count reaches 0

4. Interactive & Applied Code

java
import java.util.concurrent.*; public class SynchronizationUtilitiesDemo { public static void main(String[] args) throws Exception { demonstrateSemaphore(); demonstrateCountDownLatch(); demonstrateCyclicBarrier(); } static void demonstrateSemaphore() throws Exception { System.out.println("=== SEMAPHORE ==="); Semaphore parking = new Semaphore(3); // 3 parking spots for (int i = 1; i <= 6; i++) { final int carId = i; new Thread(() -> { try { System.out.println("Car " + carId + " trying to park..."); parking.acquire(); // Get permit System.out.println("Car " + carId + " parked!"); Thread.sleep(2000); // Parked for 2 seconds System.out.println("Car " + carId + " leaving..."); } catch (InterruptedException e) { } finally { parking.release(); // Return permit } }).start(); } Thread.sleep(10000); // Let demo finish } static void demonstrateCountDownLatch() throws Exception { System.out.println("\n=== COUNT DOWN LATCH ==="); int WORKERS = 3; CountDownLatch latch = new CountDownLatch(WORKERS); // Worker threads for (int i = 1; i <= WORKERS; i++) { final int workerId = i; new Thread(() -> { try { System.out.println("Worker " + workerId + " starting..."); Thread.sleep((long) (Math.random() * 2000)); System.out.println("Worker " + workerId + " finished!"); latch.countDown(); // Signal completion } catch (InterruptedException e) {} }).start(); } // Main thread waits System.out.println("Main thread waiting for workers..."); latch.await(); // Blocks until count reaches 0 System.out.println("All workers done! Continue main task."); } static void demonstrateCyclicBarrier() throws Exception { System.out.println("\n=== CYCLIC BARRIER ==="); int PARTIES = 3; CyclicBarrier barrier = new CyclicBarrier(PARTIES, () -> { System.out.println("*** All parties arrived! Taking group photo ***"); }); for (int i = 1; i <= PARTIES; i++) { final int touristId = i; new Thread(() -> { try { System.out.println("Tourist " + touristId + " traveling..."); Thread.sleep((long) (Math.random() * 2000)); System.out.println("Tourist " + touristId + " arrived at checkpoint"); barrier.await(); // Wait for others System.out.println("Tourist " + touristId + " continuing journey"); } catch (Exception e) {} }).start(); } Thread.sleep(5000); } } // Real-world example: Connection pool class ConnectionPool { private final Semaphore semaphore; private final java.util.List<Connection> connections; public ConnectionPool(int poolSize) { this.semaphore = new Semaphore(poolSize); this.connections = new java.util.ArrayList<>(); for (int i = 0; i < poolSize; i++) { connections.add(new Connection("Conn-" + i)); } } public Connection acquire() throws InterruptedException { semaphore.acquire(); // Wait for available connection return getConnection(); } public void release(Connection conn) { returnConnection(conn); semaphore.release(); // Free up permit } private synchronized Connection getConnection() { return connections.remove(0); } private synchronized void returnConnection(Connection conn) { connections.add(conn); } static class Connection { String id; Connection(String id) { this.id = id; } } }

5. The Comparison & Decision Layer

UtilityPurposeReusable?Use Case
SemaphoreLimit access✅ YesResource pools
CountDownLatchOne-time wait❌ NoStartup coordination
CyclicBarrierMutual wait✅ YesParallel algorithms
PhaserMulti-phase✅ YesComplex workflows

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "What's the difference between CountDownLatch and CyclicBarrier?" Answer:

  • CountDownLatch: One-time use, count down to zero, threads don't wait for each other (fire-and-forget)
  • CyclicBarrier: Reusable, all threads wait for each other at barrier
java
// CountDownLatch (one-time) CountDownLatch latch = new CountDownLatch(3); latch.countDown(); // Decrement latch.await(); // Wait for 0 // Cannot reuse! // CyclicBarrier (reusable) CyclicBarrier barrier = new CyclicBarrier(3); barrier.await(); // Wait for 3 threads // Resets automatically! Can await() again

Pro-Tip: Fair vs Unfair Semaphore:

java
// Unfair (default) - faster, no ordering guarantee Semaphore semaphore = new Semaphore(5); // Fair - FIFO ordering, slightly slower Semaphore fairSemaphore = new Semaphore(5, true);

Use fair semaphore to prevent thread starvation (thread waits forever).

Topics Covered

Java FundamentalsConcurrency

Tags

#java#multithreading#threads#concurrency#parallelism

Last Updated

2025-02-01