Contributed by
Jérémy Derussé
in #21093.

在计算机科学中,一个 lock"a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution"(字面义:一种同步架构,在一个有多个执行进程的环境中,强行限制对资源的访问)。在Symfony程序中,锁定被用在,例如,防止服务器在执行某个给定命令时,有一个以上的进程。

在Symfony 2.6中我们添加了一个 LockHandler 功能,以简化创建锁定。在内部,这一工具使用了PHP的 flock() 函数,因此它是基于文件系统的,不可以在创建共享在不同服务器之间的锁定。

在Symfony 3.3中我们决定扩展此架构,创建了一个全新的 Lock组件 ,辅以如下功能:

  • 支持多个lock stores: flock(), PHP Semaphore extension, Redis 以及 Memcache;
  • 可创建 blocking, non-blocking and auto-expiring 的锁定;
  • 能够组合多个stores (如,同时使用 Redis 和 flock),还能应用不同的策略(consensus, majority)。

当作为独立组件使用时,你要先定义要使用的store,然后创建一个factory以创建锁定:

1
2
3
4
5
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\Store\SemaphoreStore;
 
$store = new SemaphoreStore();
$factory = new Factory($store);

然后,你可以获取,检查,接续或释放锁定(acquire, check, renew or release the locks)。

1
2
3
4
5
6
7
8
9
10
11
// ...
$lock = $factory->createLock('pdf-invoice-generation');
 
if ($lock->acquire()) {
    // The resource "pdf-invoice-generation" is locked.
    // You can compute and generate invoice safely here.
    // "pdf-invoice-generation" 这个资源被锁定了。
    // 你可以在此安全的计算和生成“发票”。
 
    $lock->release();
}

当在Symfony框架中使用时,用法被极大的简化了。首先,定义要使用的锁定之类型(如果需要,你可以定义一个以上的锁定):

1
2
3
4
5
6
7
8
9
10
# app/config/config.yml
framework:
    # these are all the supported flock stores
    # 这里是全部被支持的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']

然后,使用 lock 服务以获取,检查,接续或释放锁定:

1
2
3
4
5
6
7
8
9
10
11
12
// non-blocking, non-expiring
$lock = $container->get('lock')->acquire();
// blocking, non-expiring (无限期等待直到锁定被获取)
$lock = $container->get('lock')->acquire(true);
// non-blocking, expiring in 60 seconds (unless the lock is refreshed)
// non-blocking, 60秒过期(除非锁定被刷新)
$lock = $container->get('lock')->acquire(false, 60);
 
// normal operations on the lock / 常规的锁定操作
$lock->isAcquired();
$lock->refresh();
$lock->release();

本组件的文档 已经准备好,但尚未合并,与Symfony框架整合 同样被定义了,但状态是挂起待合并。