ConcurrencyPHPverifiedVerified

Semaphore Pattern in PHP

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 PHP

1Step 1: Define a counting semaphore

class Semaphore
{
    private int $permits;

    public function __construct(int $maxPermits)
    {
        $this->permits = $maxPermits;
    }

2Step 2: Acquire a permit (decrement)

    public function acquire(): bool
    {
        if ($this->permits <= 0) {
            return false;
        }
        $this->permits--;
        return true;
    }

3Step 3: Release a permit (increment)

    public function release(): void
    {
        $this->permits++;
    }

    public function available(): int
    {
        return $this->permits;
    }
}

4Step 4: Use Fibers to simulate concurrent resource access

class ConnectionPool
{
    private Semaphore $semaphore;

    public function __construct(int $maxConnections)
    {
        $this->semaphore = new Semaphore($maxConnections);
    }

    public function withConnection(callable $work): \Fiber
    {
        return new \Fiber(function () use ($work): void {
            while (!$this->semaphore->acquire()) {
                \Fiber::suspend('waiting');
            }

            try {
                $work();
            } finally {
                $this->semaphore->release();
            }
        });
    }
}

// Usage
$pool = new ConnectionPool(2);
$fibers = [];

for ($i = 0; $i < 5; $i++) {
    $id = $i;
    $fibers[] = $pool->withConnection(function () use ($id): void {
        echo "Worker {$id} using connection\n";
    });
}

foreach ($fibers as $fiber) { $fiber->start(); }
for ($tick = 0; $tick < 20; $tick++) {
    foreach ($fibers as $fiber) {
        if ($fiber->isSuspended()) $fiber->resume();
    }
}

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.