File locking文件锁定是一种架构,通过在任何特定时间点只允许一个用户或进程,来限制访问电脑上的文件。早在1963年这种架构就被引入,但在Symfony中初登场是从2.6版起。
全新的LockHandler
类,提供了一个简单的抽象层,借助一个file lock来锁定任何东西。它的最常见使用场景通过锁定命令来避免竞争现象,因此同一命令不能被不同的线程并发执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\LockHandler;
class UpdateContentsCommand extends Command
{
protected function configure()
{
// ...
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// create the lock 创建锁定
$lock = new LockHandler('update:contents');
if (!$lock->lock()) {
$output->writeln('The command is already running in another process.');
return 0;
}
// ... do some task 进行一些操作
// (optional) release the lock (otherwise, PHP will do it
// for you automatically)
// (可选的)释放锁定(否则,PHP将替你自动完成)
$lock->release();
}
} |
LockHandler
的构造器把第一个参数当作锁定识别符,将被用于创建锁定的文件的名字的一部分。默认情况是,锁定被创建在系统的临时文件夹中。如果你希望使用一个特定目录,可以将其作为构造器的第二个可选参数传入。
如果锁定被接受,lock()
方法返回true
,否则返回false
。此外,你还可以“可选地”传入一个布尔值参数,用于指明是否需要“在请求的锁定被释放之前进行等待”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class UpdateContentsCommand extends Command
{
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
// create the lock 创建锁定
$lock = new LockHandler('update:contents');
// wait for the lock release as long as necessary 等待锁定释放
if (!$lock->lock(true)) {
$output->writeln('The command is already running in another process.');
return 0;
}
// ...
}
} |
锁定控制器被刻意限制为“基于文件的锁定”,因为要让它对网络或数据库进行锁定将会无比复杂。这意味着它只能工作在“仅使用一个宿主”时。如果你有多个宿主,你就无法使用这个helper。