Grégoire Pineau
Contributed by Grégoire Pineau in #35780

Symfony introduced the Lock component in Symfony 3.4, to provide a mechanism to grant exclusive access to a shared resource. In some cases, it's not enough to provide access to a single process and you need to allow access to multiple concurrent processes.

According to the Wikipedia definition, a semaphore is a variable or abstract data type used to control access to a common resource by multiple processes in a concurrent system such as a multitasking operating system. Broadly speaking, a semaphore allows N process to access a resource, and a lock is a semaphore where N = 1.

In Symfony 5.2 we're introducing a new Semaphore component. Instead of using a simple variable, the Semaphore component uses a store (e.g. a Redis server). First, create the store:

1
2
3
4
5
6
7
use Symfony\Component\Semaphore\SemaphoreFactory;
use Symfony\Component\Semaphore\Store\RedisStore;

$redis = new Redis();
$redis->connect('172.17.0.2');
$store = new RedisStore($redis);
$factory = new SemaphoreFactory($store);

Then, use that factory to actually create a semaphore:

1
2
3
4
5
6
7
8
// ...
$semaphore = $factory->createSemaphore('pdf-invoice-generation', 2);
if ($semaphore->acquire()) {
    // The resource "pdf-invoice-generation" is locked.
    // You can compute and generate invoice safely here.

    $semaphore->release();
}

Given the single-threaded nature of PHP, to fully use the semaphore in concurrent process you must run N workers. In each worker you look for a job to do. If you get a job, try to acquire a semaphore. If you acquire it, process the job; otherwise, try to find another job.

Read the Semaphore component documentation to learn all about it.

Published in #Living on the edge