Sleeping Barber problem in Process Synchronization (original) (raw)

Last Updated : 3 Sep, 2025

The Sleeping Barber Problem is a classic process synchronization problem that demonstrates how to manage concurrent processes. It models a barbershop scenario with a barber chair and a waiting room, where synchronization mechanisms like semaphores are used to manage access. The rules ensure that only one customer occupies the barber chair at a time, the barber works whenever a customer is present, and sleeps when no customers are waiting.

**Problem statement

1. One barber, one barber chair, and N waiting chairs.
2. If no customer, the barber sleeps in his chair.
3. A customer who arrives:

The challenge is to safely synchronize customers and the barber so that:

dining_philospher-problem-image

Sleeping Barber Problem

Synchronization Solution

We use three semaphores:

  1. Customers counts waiting customers.
  2. Barber signals when the barber is ready.
  3. Mutex ensures mutual exclusion when accessing chairs.

**Algorithm

**Customer

**Barber

dining_philospher-problem-flowchart

Sleeping Barber Problem flowchart

Pseudocode

Semaphore Customers = 0;
Semaphore Barber = 0;
Mutex Seats = 1;
int FreeSeats = N;

Barber {
while(true) {
down(Customers); // wait for customer
down(Seats);
FreeSeats++; // one waiting chair becomes free
up(Barber); // barber ready
up(Seats);

// cut hair
}
}

Customer {
while(true) {
down(Seats);
if(FreeSeats > 0) {
FreeSeats--; // take a seat
up(Customers); // notify barber
up(Seats);
down(Barber); // wait for barber
// get haircut

} else {
up(Seats); // leave if no seat
}
}
}

**Explanation:

Here's the code implementation of the Sleeping Barber Problem using semaphores:

C++ `

#include #include #include #include #include #include #include

std::mutex mtx; std::condition_variable cv; std::vector waiting; const int NUM_CHAIRS = 3;

void barber() { while (true) { std::unique_lockstd::mutex lock(mtx); std::cout << "Barber is sleeping..." << std::endl; cv.wait(lock, []{ return !waiting.empty(); }); int cust = waiting.front(); waiting.erase(waiting.begin()); std::cout << "Barber cutting hair of customer " << cust << std::endl; lock.unlock(); std::this_thread::sleep_for(std::chrono::seconds(rand() % 3 + 1)); std::cout << "Barber finished with customer " << cust << std::endl; lock.lock(); cv.notify_one(); } }

void customer(int i) { std::this_thread::sleep_for(std::chrono::seconds(rand() % 4 + 1)); std::unique_lockstd::mutex lock(mtx); if (waiting.size() < NUM_CHAIRS) { waiting.push_back(i); std::cout << "Customer " << i << " waiting" << std::endl; lock.unlock(); cv.notify_one(); lock.lock(); cv.wait(lock, []{ return waiting.front() != i; }); std::cout << "Customer " << i << " got haircut" << std::endl; } else { std::cout << "Customer " << i << " left (no seat)" << std::endl; } }

int main() { std::thread t1(barber); for (int i = 0; i < 5; ++i) { std::thread t(customer, i); t.detach(); } t1.join(); return 0; }

C

#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <time.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cv = PTHREAD_COND_INITIALIZER; int waiting[3]; int waiting_count = 0; const int NUM_CHAIRS = 3;

void* barber(void* arg) { while (1) { pthread_mutex_lock(&mtx); while (waiting_count == 0) { pthread_cond_wait(&cv, &mtx); } int cust = waiting[0]; for (int i = 0; i < waiting_count - 1; ++i) { waiting[i] = waiting[i + 1]; } waiting_count--; pthread_mutex_unlock(&mtx); printf("Barber cutting hair of customer %d\n", cust); sleep(rand() % 3 + 1); printf("Barber finished with customer %d\n", cust); pthread_mutex_lock(&mtx); pthread_cond_signal(&cv); } return NULL; }

void* customer(void* arg) { int i = ((int)arg); sleep(rand() % 4 + 1); pthread_mutex_lock(&mtx); if (waiting_count < NUM_CHAIRS) { waiting[waiting_count++] = i; printf("Customer %d waiting\n", i); pthread_cond_signal(&cv); while (waiting[0] != i) { pthread_cond_wait(&cv, &mtx); } printf("Customer %d got haircut\n", i); } else { printf("Customer %d left (no seat)\n", i); } pthread_mutex_unlock(&mtx); return NULL; }

int main() { pthread_t t1, t[5]; pthread_create(&t1, NULL, barber, NULL); for (int i = 0; i < 5; ++i) { int* arg = malloc(sizeof(int)); *arg = i; pthread_create(&t[i], NULL, customer, arg); } for (int i = 0; i < 5; ++i) { pthread_join(t[i], NULL); } pthread_join(t1, NULL); return 0; }

Java

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.Random;

public class BarberShop { private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private final int[] waiting = new int[3]; private int waitingCount = 0; private static final int NUM_CHAIRS = 3; private Random random = new Random();

public void barber() {
    while (true) {
        lock.lock();
        try {
            while (waitingCount == 0) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int cust = waiting[0];
            for (int i = 0; i < waitingCount - 1; ++i) {
                waiting[i] = waiting[i + 1];
            }
            waitingCount--;
            System.out.println("Barber cutting hair of customer " + cust);
        } finally {
            lock.unlock();
        }
        try {
            Thread.sleep(random.nextInt(3) + 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Barber finished with customer " + cust);
        lock.lock();
        try {
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}

public void customer(int i) {
    try {
        Thread.sleep(random.nextInt(4) + 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    lock.lock();
    try {
        if (waitingCount < NUM_CHAIRS) {
            waiting[waitingCount++] = i;
            System.out.println("Customer " + i + " waiting");
            condition.signal();
            while (waiting[0] != i) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Customer " + i + " got haircut");
        } else {
            System.out.println("Customer " + i + " left (no seat)");
        }
    } finally {
        lock.unlock();
    }
}

public static void main(String[] args) {
    BarberShop barberShop = new BarberShop();
    Thread barberThread = new Thread(() -> barberShop.barber());
    barberThread.start();
    for (int i = 0; i < 5; ++i) {
        new Thread(() -> barberShop.customer(i)).start();
    }
    try {
        barberThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

Python

import threading import random import time

mtx = threading.Lock() cv = threading.Condition(mtx) waiting = [] NUM_CHAIRS = 3

def barber(): while True: with cv: while not waiting: cv.wait() cust = waiting.pop(0) print(f'Barber cutting hair of customer {cust}') time.sleep(random.randint(1, 3)) print(f'Barber finished with customer {cust}') with cv: cv.notify()

def customer(i): time.sleep(random.randint(1, 4)) with cv: if len(waiting) < NUM_CHAIRS: waiting.append(i) print(f'Customer {i} waiting') cv.notify() while waiting[0] != i: cv.wait() print(f'Customer {i} got haircut') else: print(f'Customer {i} left (no seat)')

if name == 'main': t1 = threading.Thread(target=barber) t1.start() for i in range(5): threading.Thread(target=customer, args=(i,)).start() t1.join()

`