New in Symfony 3.3: Lock component
March 27, 2017 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Contributed by
Jérémy Derussé
in #21093.
WARNING: This component was finally removed from Symfony 3.3 and postponed for Symfony 3.4, to have more time to polish and stabilize it.
In computer science, a lock is "a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution". In Symfony applications locks are used for example to prevent more than one simultaneous execution of a given command in the server.
In Symfony 2.6 we added a LockHandler utility to simplify the creation of
locks. Internally, this utility uses PHP's flock()
function, so it's based
on the file system and cannot create locks shared in different servers.
In Symfony 3.3 we decided to extend this mechanism and we created a brand new Lock component with these features:
- It supports multiple lock stores:
flock()
, PHP Semaphore extension, Redis and Memcache; - It creates blocking, non-blocking and auto-expiring locks;
- It allows combining several stores (e.g. Redis and flock simultaneously) and it can apply different strategies (consensus, majority).
When used as an independent component, you first define the store to use and then create a factory used to create the locks:
1 2 3 4 5
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\Store\SemaphoreStore;
$store = new SemaphoreStore();
$factory = new Factory($store);
Then, you can acquire, check, renew or release the locks:
1 2 3 4 5 6 7 8 9
// ...
$lock = $factory->createLock('pdf-invoice-generation');
if ($lock->acquire()) {
// The resource "pdf-invoice-generation" is locked.
// You can compute and generate invoice safely here.
$lock->release();
}
When used within the Symfony framework, its usage is greatly simplified. First, define the type of lock to use (you can define more than one lock type if needed):
1 2 3 4 5 6 7 8 9
# app/config/config.yml
framework:
# these are all the supported flock stores
lock: 'flock'
lock: 'semaphore'
lock: 'memcached://m1.docker'
lock: ['memcached://m1.docker', 'memcached://m2.docker']
lock: 'redis://r1.docker'
lock: ['redis://r1.docker', 'redis://r2.docker']
Then, use the lock
service to acquire, check, renew or release the locks:
1 2 3 4 5 6 7 8 9 10 11
// non-blocking, non-expiring
$lock = $container->get('lock')->acquire();
// blocking, non-expiring (waits indefinitely until the lock is acquired)
$lock = $container->get('lock')->acquire(true);
// non-blocking, expiring in 60 seconds (unless the lock is refreshed)
$lock = $container->get('lock')->acquire(false, 60);
// normal operations on the lock
$lock->isAcquired();
$lock->refresh();
$lock->release();
The documentation of the component is ready but not merged yet and the integration with the Symfony framework is also defined but pending to be merged.
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
A little typo :
blocking, non-expiring (waits indefinitely until the lock is acquired)
Should be
blocking, non-expiring (waits indefinitely until the lock is released)