ConcurrencyC++verifiedVerified

Semaphore Pattern in C++

Control access to a finite pool of resources by maintaining a counter that threads atomically increment (release) and decrement (acquire), blocking when the count reaches zero.

How to Implement the Semaphore Pattern in C++

1Step 1: Use counting_semaphore to limit concurrent access

std::counting_semaphore<3> pool(3); // max 3 concurrent

void accessResource(int id) {
    pool.acquire();
    std::cout << std::format("Thread {} acquired access\n", id);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::cout << std::format("Thread {} releasing\n", id);
    pool.release();
}

2Step 2: Launch more threads than the semaphore allows

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 8; ++i)
        threads.emplace_back(accessResource, i);

    for (auto& t : threads) t.join();
    std::cout << "All done\n";
}

Semaphore Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Semaphore Pattern in the Real World

Imagine a car park with exactly three spaces. A ticket machine at the entrance (the semaphore) issues a ticket only if spaces remain, lifting the barrier; arriving drivers with no ticket available must wait. When a car exits, the machine automatically increments its counter and releases the next waiting driver — the car park never exceeds capacity.