<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jim Rogers</title>
    <description>The latest articles on DEV Community by Jim Rogers (@jim_rogers_c227114e275d64).</description>
    <link>https://dev.to/jim_rogers_c227114e275d64</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3895134%2F5c813a14-202f-46b5-ac5b-cc1e654b7eec.jpg</url>
      <title>DEV Community: Jim Rogers</title>
      <link>https://dev.to/jim_rogers_c227114e275d64</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jim_rogers_c227114e275d64"/>
    <language>en</language>
    <item>
      <title>Sleeping Barber Problem</title>
      <dc:creator>Jim Rogers</dc:creator>
      <pubDate>Fri, 24 Apr 2026 03:19:54 +0000</pubDate>
      <link>https://dev.to/jim_rogers_c227114e275d64/sleeping-barber-problem-38na</link>
      <guid>https://dev.to/jim_rogers_c227114e275d64/sleeping-barber-problem-38na</guid>
      <description>&lt;h2&gt;
  
  
  Sleeping Barber Problem
&lt;/h2&gt;

&lt;p&gt;The sleeping barber problem is a classic concurrency problem introduced by Edsger Dijkstra in 1965. It illustrates the challenges of coordinating multiple processes sharing limited resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scenario
&lt;/h2&gt;

&lt;p&gt;A barbershop has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 barber with 1 barber chair &lt;/li&gt;
&lt;li&gt;A waiting room with N chairs &lt;/li&gt;
&lt;li&gt;Customers arriving at random intervals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The rules:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If no customers are present, the barber sleeps in their chair &lt;/li&gt;
&lt;li&gt;When a customer arrives and the barber is asleep, they wake the barber up &lt;/li&gt;
&lt;li&gt;If the barber is busy and chairs are available, the customer sits and waits &lt;/li&gt;
&lt;li&gt;If all waiting chairs are full, the customer leaves&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Concurrency Challenges
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This maps directly to real OS/threading problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Race conditions — Without proper synchronization, a customer might check "is the barber free?" and get preempted before sitting down. The barber, seeing no one, goes to sleep. The customer then sits — and both wait forever (a deadlock).&lt;/li&gt;
&lt;li&gt;Starvation — If customers keep arriving continuously, some may never get served.&lt;/li&gt;
&lt;li&gt;Lost wakeups — A customer might signal the barber to wake up, but the signal is missed because the barber hasn't gone to sleep yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution (using semaphores)
&lt;/h2&gt;

&lt;p&gt;Three semaphores are typically used:&lt;br&gt;
customers  = 0   // counts waiting customers (signals barber to wake)&lt;br&gt;
barber     = 0   // signals a customer that barber is ready&lt;br&gt;
mutex      = 1   // protects the shared waiting count&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Barber's loop:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="n"&gt;arrives&lt;/span&gt;
    &lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
    &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;       &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;fewer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt;
    &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;tell&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;m ready
    release(mutex)
    cut_hair()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Each customer:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;wake&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nf"&gt;barber &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="n"&gt;yourself&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;barber&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;me&lt;/span&gt;
    &lt;span class="nf"&gt;get_haircut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;seats&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;leave&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;p&gt;The sleeping barber is a direct analogy for many real systems:&lt;br&gt;
&lt;em&gt;Barbershop&lt;/em&gt;&lt;br&gt;
Real system&lt;br&gt;
&lt;em&gt;Barber&lt;/em&gt;&lt;br&gt;
Worker thread / server&lt;br&gt;
&lt;em&gt;Waiting chairs&lt;/em&gt;&lt;br&gt;
Thread pool / request queue&lt;br&gt;
&lt;em&gt;Customer&lt;/em&gt;&lt;br&gt;
Incoming task / connection&lt;br&gt;
&lt;em&gt;Customer leaving&lt;/em&gt;&lt;br&gt;
Request rejection (HTTP 503)&lt;br&gt;
&lt;em&gt;Barber sleeping&lt;/em&gt;&lt;br&gt;
Thread blocking on a condition variable&lt;/p&gt;

&lt;p&gt;It's essentially the foundation of thread pool design — every web server (nginx, Node.js worker threads, Java ExecutorService) solves a variant of this problem. The waiting room size becomes your queue capacity, and the number of barbers maps to your worker count.&lt;/p&gt;
&lt;h2&gt;
  
  
  Orderly Shutdown
&lt;/h2&gt;

&lt;p&gt;Orderly shutdown is one of the trickier real-world concurrency problems because most textbook examples use a fixed loop count — but production systems run indefinitely until told to stop. Academic examples ignore this problem by establishing a fixed number if iterations a concurrent solution will execute, but real-world production solutions need a means to provide orderly shutdown based on an external influence or message.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;You need every thread to:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finish what it's currently doing (don't corrupt state mid-operation) &lt;/li&gt;
&lt;li&gt;Stop accepting new work &lt;/li&gt;
&lt;li&gt;Drain any buffered/queued work (sometimes) &lt;/li&gt;
&lt;li&gt;Release resources cleanly (locks, file handles, sockets) &lt;/li&gt;
&lt;li&gt;Signal completion so the main thread knows it's safe to exit 
These goals can conflict. Draining the queue vs. stopping promptly is a genuine design tension.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Common Mechanisms
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Poison Pill&lt;/em&gt;
Insert a sentinel value into the work queue that means "stop when you see this."
&lt;em&gt;python&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;POISON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;POISON&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;POISON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# re-post so other workers also see it
&lt;/span&gt;            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Pros: Simple, respects queue ordering (drains work before stopping) &lt;br&gt;
Cons: Queue must be FIFO; hard to use with priority queues; re-posting is fragile with multiple workers&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Shared Stop Flag (with careful memory visibility)&lt;/em&gt;
&lt;em&gt;python&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;

&lt;span class="n"&gt;stop_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;stop_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_set&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# must time out — not block forever
&lt;/span&gt;            &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# re-check the stop flag
&lt;/span&gt;
&lt;span class="c1"&gt;# Shutdown:
&lt;/span&gt;&lt;span class="n"&gt;stop_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The critical subtlety here is the timeout on the blocking call. A thread blocked indefinitely on queue.get() will never check the flag — so you must wake it up periodically. This introduces a latency vs. CPU burn tradeoff in the timeout value.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Interrupt / Cancellation Token (Go-style context)&lt;/em&gt;
Go's context package makes this idiomatic:
&lt;em&gt;go&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="c"&gt;// shutdown signal received&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="c"&gt;// channel closed&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Shutdown:&lt;/span&gt;
&lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c"&gt;// derived from context.WithCancel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The select races both channels simultaneously — no polling, no timeout gymnastics. This is arguably the cleanest model because cancellation is a first-class value passed through the call graph, not a global side channel.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Two-Phase Shutdown&lt;/em&gt;
Used when you need to distinguish "stop accepting new work" from "finish existing work":
Phase 1 — Soft stop:

&lt;ul&gt;
&lt;li&gt;Close the intake gate (reject new submissions)&lt;/li&gt;
&lt;li&gt;Let workers drain the queue naturally&lt;/li&gt;
&lt;li&gt;Set a deadline&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phase 2 — Hard stop (if deadline exceeded):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interrupt blocked workers&lt;/li&gt;
&lt;li&gt;Abandon remaining queue items&lt;/li&gt;
&lt;li&gt;Force exit
&lt;em&gt;This is exactly what Java's ExecutorService provides:
java&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;                          &lt;span class="c1"&gt;// phase 1: no new tasks&lt;/span&gt;
&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;awaitTermination&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;    &lt;span class="c1"&gt;// wait for drain&lt;/span&gt;
    &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdownNow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// phase 2: interrupt workers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Deeper Design Issues
&lt;/h2&gt;

&lt;p&gt;Who owns the shutdown signal? If any thread can trigger shutdown, you need coordination so they don't race each other. Typically one designated thread (main, signal handler) owns it.&lt;br&gt;
What about blocked I/O? A thread blocked on a socket read or a wait() won't notice a flag. You need to either close the underlying resource (causing an exception) or use interruptible blocking calls.&lt;br&gt;
The TOCTOU trap on shutdown:&lt;br&gt;
Thread A checks: is_shutting_down? → false&lt;br&gt;
                                        Main sets: is_shutting_down = true&lt;br&gt;
Thread A submits new work              ← work submitted after shutdown began&lt;br&gt;
The intake gate must be closed atomically with the flag — usually requiring a mutex around both the check and the submission.&lt;br&gt;
Signaling completion back up: join() / await on a barrier or latch is the standard pattern. The main thread must not exit until all workers confirm they're done, or destructors will fire under live threads.&lt;br&gt;
main:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal shutdown
    latch.await()    ← blocks here
    cleanup()
    exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;each worker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ... finish work ...
    latch.countDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The General Principle&lt;br&gt;
The root difficulty is that blocking and polling are duals of each other — blocking is efficient but uninterruptible, polling is interruptible but wastes CPU. Every shutdown mechanism is essentially a negotiation between these two. The cleanest designs (Go's context, Java's Future.cancel) make cancellation a first-class concern from the start rather than retrofitting a flag onto blocking code.&lt;/p&gt;
&lt;h2&gt;
  
  
  A classical C implementation of the Sleeping Barber problem
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define NUM_CUSTOMERS 20
#define NUM_SEATS 5
&lt;/span&gt;
&lt;span class="n"&gt;pthread_mutex_t&lt;/span&gt; &lt;span class="n"&gt;mutex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PTHREAD_MUTEX_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pthread_cond_t&lt;/span&gt; &lt;span class="n"&gt;barber_ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PTHREAD_COND_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pthread_cond_t&lt;/span&gt; &lt;span class="n"&gt;customer_ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PTHREAD_COND_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// number of customers waiting&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;barber_sleeping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// barber initially asleep&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;barber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Sleep if no customers&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;barber_sleeping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Barber: No customers, going to sleep.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;pthread_cond_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customer_ready&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// A customer is ready&lt;/span&gt;
        &lt;span class="n"&gt;waiting&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Barber: Taking a customer. Waiting room count = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Wake the customer&lt;/span&gt;
        &lt;span class="n"&gt;pthread_cond_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;barber_ready&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;barber_sleeping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Cut hair (simulate time)&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Barber: Cutting hair...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;usleep&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;NUM_SEATS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;waiting&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Customer %d: Sitting in waiting room. Waiting = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;waiting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Wake the barber if needed&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barber_sleeping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Customer %d: Waking the barber.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;pthread_cond_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customer_ready&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Wait until the barber is ready&lt;/span&gt;
        &lt;span class="n"&gt;pthread_cond_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;barber_ready&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Get haircut&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Customer %d: Getting a haircut.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;usleep&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// No seats available&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Customer %d: No seats available, leaving.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;srand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;barber_thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;customer_threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NUM_CUSTOMERS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="n"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;barber_thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;barber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NUM_CUSTOMERS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;NUM_CUSTOMERS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;usleep&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// random arrival&lt;/span&gt;
        &lt;span class="n"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customer_threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;NUM_CUSTOMERS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pthread_join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// In classical C examples, the barber runs forever.&lt;/span&gt;
    &lt;span class="c1"&gt;// A real system would need a shutdown mechanism.&lt;/span&gt;

    &lt;span class="n"&gt;pthread_cancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barber_thread&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;pthread_join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barber_thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Fragility Analysis of the C Example
&lt;/h2&gt;

&lt;p&gt;The classical C implementation of the Sleeping Barber problem works — but only because the programmer manually enforces every concurrency invariant the language itself does not understand. The code is correct only as long as the programmer maintains a delicate choreography of mutexes, condition variables, and shared‑state checks. Several categories of fragility are inherent to this approach.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lost Wakeups
&lt;/h2&gt;

&lt;p&gt;Condition variables do not store signals. If a customer signals the barber before the barber executes pthread_cond_wait, the signal is lost forever.&lt;br&gt;
This is why the barber must use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waiting&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pthread_cond_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;customer_ready&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The loop is not stylistic — it is a defensive pattern required to avoid a race the language cannot prevent.&lt;/li&gt;
&lt;li&gt;A single misplaced if instead of while reintroduces the lost‑wakeup bug.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Spurious Wake-ups
&lt;/h2&gt;

&lt;p&gt;POSIX explicitly allows condition variables to wake up for no reason. This forces every wait to be wrapped in a loop that rechecks the predicate.&lt;br&gt;
The programmer must remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;never trust a wake-up &lt;/li&gt;
&lt;li&gt;always recheck the condition &lt;/li&gt;
&lt;li&gt;always hold the mutex while checking&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Manual Queue Invariants
&lt;/h2&gt;

&lt;p&gt;The waiting room count (waiting) is a shared variable with a non‑trivial invariant:&lt;br&gt;
&lt;code&gt;0 ≤ waiting ≤ NUM_SEATS&lt;/code&gt;&lt;br&gt;
In C, the programmer must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;protect it with the correct mutex &lt;/li&gt;
&lt;li&gt;increment and decrement it in the right places &lt;/li&gt;
&lt;li&gt;ensure no path forgets to unlock the mutex &lt;/li&gt;
&lt;li&gt;ensure no early return violates the invariant 
A single missing unlock or misordered update can corrupt the state.
Mutex Discipline Is Entirely Manual
Every shared variable must be accessed only while holding the correct mutex. Nothing in C enforces this.
If a future maintainer adds:
&lt;code&gt;if (waiting == 0) { ... }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;outside the mutex, the program becomes subtly incorrect. The compiler cannot help. The runtime cannot help. The language cannot help.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shutdown Is Not Structurally Supported
&lt;/h2&gt;

&lt;p&gt;The classical C example typically runs forever because orderly shutdown is difficult:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A worker may be blocked on pthread_cond_wait &lt;/li&gt;
&lt;li&gt;A customer may be blocked on pthread_cond_wait &lt;/li&gt;
&lt;li&gt;A shutdown flag must be checked, but blocked threads cannot check it &lt;/li&gt;
&lt;li&gt;pthread_cond_broadcast must be used carefully &lt;/li&gt;
&lt;li&gt;Threads may wake up and race to submit new work after shutdown begins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The programmer must manually coordinate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;flag setting &lt;/li&gt;
&lt;li&gt;mutex locking &lt;/li&gt;
&lt;li&gt;condition broadcasts &lt;/li&gt;
&lt;li&gt;thread joins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Correctness Depends on Programmer Memory, Not Language Semantics&lt;br&gt;
The C solution is correct only because the programmer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remembered to lock before checking &lt;/li&gt;
&lt;li&gt;remembered to re-check after waking &lt;/li&gt;
&lt;li&gt;remembered to signal in the right order &lt;/li&gt;
&lt;li&gt;remembered to guard every shared variable &lt;/li&gt;
&lt;li&gt;remembered to maintain the queue invariant &lt;/li&gt;
&lt;li&gt;remembered to avoid TOCTOU races&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a concurrency model. It is a set of conventions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Ada Solves These Problems at the Language Level
&lt;/h2&gt;

&lt;p&gt;The classical C solution demonstrates the essential difficulty: the language has no concurrency semantics. Threads, mutexes, and condition variables are merely library calls layered on top of a language that was never designed for concurrent execution.&lt;br&gt;
&lt;strong&gt;Ada takes the opposite approach.&lt;/strong&gt;&lt;br&gt;
Concurrency is not a library. It is part of the language’s semantic identity.&lt;br&gt;
Where C requires the programmer to manually maintain invariants, Ada provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;protected objects with implicit locking &lt;/li&gt;
&lt;li&gt;entries with built‑in FIFO queuing &lt;/li&gt;
&lt;li&gt;barrier conditions that eliminate lost wakeups &lt;/li&gt;
&lt;li&gt;select statements that express conditional synchronization directly &lt;/li&gt;
&lt;li&gt;rendezvous for structured synchronous communication &lt;/li&gt;
&lt;li&gt;task termination semantics that make shutdown orderly and predictable 
In C, the programmer must build a concurrency model. In Ada, the concurrency model is already there — and the programmer simply uses it.
This is why the Sleeping Barber problem is such a powerful teaching example: it exposes the difference between a language that permits concurrency and a language that understands it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Now that we’ve seen the classical C solution and the fragility inherent in manual synchronization, we can examine how Ada expresses the same problem using language‑level concurrency constructs. Notice how the invariants that must be manually maintained in C become structural guarantees in Ada.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Sleeping Barber Solution Written in Ada
&lt;/h2&gt;

&lt;p&gt;Concurrency is implemented in Ada as a core language feature. Ada tasks are active units of concurrency often implemented as OS threads. Ada tasks have been part of the Ada language since its first standardized version in 1983.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rendezvous
&lt;/h2&gt;

&lt;p&gt;Ada tasks allow direct synchronous communication between tasks using a Rendezvous mechanism. A task may declare an entry. An entry may pass data to or from the task calling the entry or the entry may be designed as an event notification with no data being passed. The task declaring an entry calls an accept statement allowing the task to respond to the task entry. The task calling the accept suspends until the called task accepts the entry. If the called task reaches its accept statement before its entry is called the calling task suspends until another task calls the entry. As soon as the entry is completed both tasks resume their concurrent behaviors.&lt;/p&gt;
&lt;h2&gt;
  
  
  Select
&lt;/h2&gt;

&lt;p&gt;Ada provides a select statement to conditionally accept an entry call. The select statement allows the called task to respond to any one of many entries it declares, or to wait a specified time for a task to call its entry, or to simply perform other behaviors if no task is suspended on its entry call. Entries are implicitly queued with a default First-In-First-Out (FIFO) queuing policy so that multiple calls to a task entry are processed in the order the entry is called.&lt;/p&gt;
&lt;h2&gt;
  
  
  Task Entry Issue
&lt;/h2&gt;

&lt;p&gt;The Ada Rendezvous pattern is powerful and very general in its usage but it cannot implement asynchronous data sharing. Asynchronous data sharing can be modeled using an intermediate task as a queuing mechanism. This model is heavy weight. In the 1995 version of the Ada standard a new feature called protected objects was added to deal with this issue.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Objects
&lt;/h2&gt;

&lt;p&gt;An Ada protected object is a passive concurrency element. It is always called by and executed within a task. The “protected” part of a protected object comes from the fact the object implements a shared memory object that controls all necessary locking implicitly. A protected object contains only private data which is accessible through methods specified within the protected object definition. There are three kinds of protected methods. &lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Procedures
&lt;/h2&gt;

&lt;p&gt;A protected procedure has unconditional exclusive read-write access to the protected object. Calling a protected procedure implicitly locks the protected object at the beginning of the procedure and unlocks the protected object at the completion of the procedure.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Entries
&lt;/h2&gt;

&lt;p&gt;Protected entries provides conditional exclusive read-write access to a protected object. A call to a protected entry only begins when the protected entry's boundary condition evaluates to TRUE. Tasks calling the protected entry while the boundary condition evaluates to FALSE are suspended in an implicit entry queue and are executed when the boundary condition becomes TRUE.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Functions
&lt;/h2&gt;

&lt;p&gt;Protected functions provide read-only access to the data in the protected object. Protected functions implement a shared read-only lock on the protected object allowing multiple overlapping function calls to be executed by calls from multiple tasks. The read-only lock is released when no tasks are calling a protected function.&lt;/p&gt;


&lt;h2&gt;
  
  
  Ada Code Example
&lt;/h2&gt;

&lt;p&gt;The primary unit of modularity in Ada is the package. An Ada package has two parts. The package specification defines the package interface while the package body contains the implementation of all the behaviors declared in the package specification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ada"&gt;&lt;code&gt;&lt;span class="kd"&gt;package&lt;/span&gt; &lt;span class="nf"&gt;Barber_Shop&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
   &lt;span class="k"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Barber&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="kd"&gt;entry&lt;/span&gt; &lt;span class="nf"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Barber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Barber_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package specification only specifies a single task named Barber. The Barber task declares one entry named Close_Shop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ada"&gt;&lt;code&gt;&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nn"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Text_IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;               &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text_IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nn"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Numerics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Float_Random&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Numerics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Float_Random&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;package&lt;/span&gt; &lt;span class="kd"&gt;body&lt;/span&gt; &lt;span class="nf"&gt;Barber_Shop&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
   &lt;span class="n"&gt;Seed&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nf"&gt;Num_Seats&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Is_Open&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Shop_Empty&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;entry&lt;/span&gt; &lt;span class="nf"&gt;Take_Seat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;entry&lt;/span&gt; &lt;span class="nf"&gt;Serve_Customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt;
      &lt;span class="n"&gt;Shop_Open&lt;/span&gt;      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;   &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Num_Seats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Is_Open&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Shop_Open&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Is_Open&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Shop_Empty&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Shop_Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;entry&lt;/span&gt; &lt;span class="nf"&gt;Take_Seat&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;Shop_Open&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Num_Seats&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Last&lt;/span&gt;
      &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Take_Seat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;entry&lt;/span&gt; &lt;span class="nf"&gt;Serve_Customer&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Occupied_Seats&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Serve_Customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Close_Shop&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="n"&gt;Shop_Open&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;False&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;------------&lt;/span&gt;
   &lt;span class="c1"&gt;-- Barber --&lt;/span&gt;
   &lt;span class="c1"&gt;------------&lt;/span&gt;

   &lt;span class="k"&gt;task&lt;/span&gt; &lt;span class="k"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Barber&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Cut_Hair&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
         &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Luigi is serving a customer."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="k"&gt;delay&lt;/span&gt; &lt;span class="nb"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Cut_Hair&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="k"&gt;loop&lt;/span&gt;
         &lt;span class="k"&gt;select&lt;/span&gt;
            &lt;span class="k"&gt;accept&lt;/span&gt; &lt;span class="n"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Luigi is closing the shop"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is_Open&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shop_Empty&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
                  &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Luigi is sleeping."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve_Customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="n"&gt;Cut_Hair&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
               &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shop_Empty&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt;
                  &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve_Customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                  &lt;span class="n"&gt;Cut_Hair&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
               &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Barber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;---------------&lt;/span&gt;
   &lt;span class="c1"&gt;-- Customers --&lt;/span&gt;
   &lt;span class="c1"&gt;---------------&lt;/span&gt;

   &lt;span class="k"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;task&lt;/span&gt; &lt;span class="k"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Customers&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
   &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="k"&gt;loop&lt;/span&gt;
         &lt;span class="k"&gt;delay&lt;/span&gt; &lt;span class="nb"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="k"&gt;select&lt;/span&gt;
            &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Take_Seat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A customer took a seat"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Shop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is_Open&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
               &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A customer left because all the seats were taken."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
               &lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"A customer left because the shop is closed."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
               &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
   &lt;span class="n"&gt;Reset&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Seed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Barber_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package body does most of the work for the Sleeping Barber example. Above the top of the package you find a context clause. The context clause declares a dependency on two language-defined packages. The first context clause declares a dependency on the package Ada.Text_IO, which is the text input/output package for Ada. The second context clause defines a dependency on Ada.Numerics.Float_Random, which provides a random number generator producing a floating point value between 0.0 and 1.0.&lt;br&gt;
Within the package body there is a declarative part and an executable part.&lt;br&gt;
The declarative part first declares a variable named Seed which is an instance of type Generator. The Generator type is declared within the Ada.Numerics.Random_Float package and is the random number seed.&lt;/p&gt;

&lt;p&gt;The type Num_Seats is declared to have valid values in the range of 0 through 5. It is a custom integer type.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Specification
&lt;/h2&gt;

&lt;p&gt;The specification for the protected object named Shop declares two functions, two entries and one procedure. The functions named Is_Open and Shop_Empty each return a Boolean value. The entries Tack_Seat and Serve_Customer are declared. The procedure Close_Shop is declared.&lt;br&gt;
The private section of the protected object specification contains two data members. Shop_Open is a Boolean type initialized to True. Occupied_Seats is an instance of Num_Seats initialize to 0. The private data members are only accessible via the functions, entries and procedure.&lt;/p&gt;
&lt;h2&gt;
  
  
  Protected Body
&lt;/h2&gt;

&lt;p&gt;The protected body implements the behaviors of the protected methods.&lt;/p&gt;

&lt;p&gt;Function Is_Open simply returns the value of the Shop_Open data member.&lt;br&gt;
Function Shop_Empty returns the result of the expression Occupied_Seats = 0. In Ada the '=' operator is the equality comparison operator.&lt;br&gt;
Entry Take_Seat only executes when Shop_Open returns True and Occupied_Seats is less than the maximum value for the Num_Seats type. When those conditions are both true the entry increments the Occupied_Seats value.&lt;br&gt;
Entry Serve_Customer only executes when Occupied_Seats is greater than 0. When that condition is true Occupied_Seats is decremented.&lt;br&gt;
Procedure Close_Shop sets Shop_Open to False.&lt;br&gt;
All locking and queuing behaviors are implicitly handled by the protected object.&lt;/p&gt;
&lt;h2&gt;
  
  
  Barber task body
&lt;/h2&gt;

&lt;p&gt;The barber task body implements the behavior of the Barber task.&lt;br&gt;
The task body contains a declarative part and an executable part. Within the declarative part the procedure Cut_Hair is declared. Cut_Hair outputs a message stating Luigi is serving a customer and then delays the task for a random number of seconds between 0.0 seconds and 3.0 seconds.&lt;br&gt;
The executable part of the task contains a basic loop that continues until the shop is closed and all awaiting customers have been served. Each iteration of that loop the task entry Close_Shop is selectively accepted. If no task is suspended on that entry the loop executes the logic following the else statement. If a task is suspended on the Close_Shop entry then the program outputs “Luigi is closing the shop” and then calls the shop.close protected procedure.&lt;br&gt;
If the shop is open then the task evaluates whether the shop is empty. If it is the task outputs “Luigi is sleeping” and then calls Shop.Serve_Customer. The task will suspend on that call until the protected object has a customer waiting in a seat. Barber then calls Cut_Hair.&lt;/p&gt;

&lt;p&gt;If the shop is closed the Barber iterates through the customers waiting to be served and serves them all then exits the outer loop. At that point the Barber task terminates.&lt;/p&gt;
&lt;h2&gt;
  
  
  Customer Task
&lt;/h2&gt;

&lt;p&gt;The customer task generates customers. The customer task has no task entry. The Customer task contains a simple loop that begins by delaying between 0.0 and 2.5 seconds. The Shop.Take_Seat protected entry is called within a select statement. If the select statement completes (the task is not queued) then the Customer task outputs “A customer took a seat”. If the Shop.Take_Seat boundary condition returns False then the Customer tasks calls Shop.Is_Open if that is true all the seats must be filled and Customer outputs “A customer left because all the seats were taken”. If Shop.Is_Open returns False then the Customer task outputs “A customer left because the shop is closed” and then exits the loop, which completes the Customer task.&lt;/p&gt;
&lt;h2&gt;
  
  
  Package executable part
&lt;/h2&gt;

&lt;p&gt;The package executable part simply initializes the random seed based on a value returned by the system clock when the package is elaborated, before any other program execution happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ada"&gt;&lt;code&gt;&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nn"&gt;Barber_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;Barber_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
   &lt;span class="k"&gt;delay&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Barber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close_Shop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Main
&lt;/h2&gt;

&lt;p&gt;The main program declares a dependency on the Barber_Shop package, delays for 60.0 seconds and calls Barber.Close. The tasks in the Barber_Shop package implicitly begin executing when Main reaches its executable part. Main is the program entry point and is therefore also the environment task. As a task it is able to call Barber.Close_Shop. Main does not complete until all the tasks started withing main, namely Barber and Customer complete. There is no explicit join() call. Ada task coordination is based on calling scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Language Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;C (pthread)&lt;/th&gt;
&lt;th&gt;Ada&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Locking&lt;/td&gt;
&lt;td&gt;Manual mutex discipline&lt;/td&gt;
&lt;td&gt;Implicit in protected objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wakeups&lt;/td&gt;
&lt;td&gt;Lost/spurious wakeups&lt;/td&gt;
&lt;td&gt;Entry barriers eliminate them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queuing&lt;/td&gt;
&lt;td&gt;Must be implemented manually&lt;/td&gt;
&lt;td&gt;FIFO queues built‑in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shutdown&lt;/td&gt;
&lt;td&gt;Flags + broadcasts&lt;/td&gt;
&lt;td&gt;Structured via entries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invariants&lt;/td&gt;
&lt;td&gt;Programmer‑maintained&lt;/td&gt;
&lt;td&gt;Compiler‑enforced&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Sleeping Barber problem is more than a concurrency puzzle — it is a lens through which we can see the philosophical difference between languages that permit concurrency and languages that understand it. C gives the programmer power and responsibility; Ada gives the programmer structure and guarantees. Both can solve the problem, but only one does so with concurrency as a first‑class semantic concept.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ada</category>
      <category>c</category>
      <category>concurrency</category>
    </item>
  </channel>
</rss>
