sk2001 / php-lock
Requires
- php: >=5.3.3
- psr/log: ~1.0
Requires (Dev)
- php-vfs/php-vfs: ~1.2
- phpspec/phpspec: ^2.4
README
php-lock 是一个库,使得资源锁定变得简单。它可以用来在写操作期间避免对文件的访问,或者防止 crontabs 之间的重叠。并且它设计得很好,可以很好地与依赖注入(例如 Symfony 容器或 Pimple)集成。
安装
使用 Composer
composer require sk2001/php-lock
使用
您可以使用一个代表文件锁的对象。然后您可以通过调用 $lock->acquire()
尝试获取该锁。如果锁定失败,它将抛出 \TH\Lock\Exception
(对于使用 Symfony Console Components 文档 构建的 CLI 工具很有用)。如果锁被获取,程序可以继续。
对文件进行独占锁定
use TH\Lock\FileLock; $lock = new FileLock('/path/to/file'); $lock->acquire(); // other processes that try to acquire a lock on the file will fail // edit /path/to/file $lock->release(); // other processes can now acquire a lock on the file
共享文件锁
use TH\Lock\FileLock; $lock = new FileLock('/path/to/file', FileLock::SHARED); $lock->acquire(); // other processes that try to acquire an exclusive lock on the file will fail, // processes that try to acquire an shared lock on the file will succeed // read /path/to/file $lock->release(); // other processes can now acquire an exclusive lock on the file if no other shared lock remains.
自动释放
$lock->release()
会在销毁锁时自动调用,因此您不需要在脚本结束时手动释放它,或者在它超出作用域时释放它。
use TH\Lock\FileLock; function batch() { $lock = new FileLock('/some/file'); $lock->acquire(); // lot of editing on file } batch(); // the lock will be released here even if $lock->release() is not called in batch()
使用锁为 crontabs
当您不希望某些 crontabs 重叠时,您可以在每个 crontab 中对相同的文件进行锁定。 TH\Lock\LockFactory
可以简化此过程,并在重叠发生时提供更有用的消息。
$lock = $factory->create('protected resource', 'process 1'); $lock->acquire(); // process 1 does stuff
$lock = $factory->create('protected resource', 'process 2'); $lock->acquire(); // process 2 does stuff
当进程 1 正在运行时,我们开始进程 2,将抛出异常:"无法获取受保护资源的独占锁",如果工厂配置了 \Psr\Log\LoggerInterface
,则会记录解释发生情况的日志。
process 1: exclusive lock acquired on protected resource
process 2: could not acquire exclusive lock on protected resource
process 2: lock released on protected resource
目前可用的唯一 LockFactory
是 TH\Lock\FileFactory
。此工厂会在指定的文件夹中自动为您的资源创建锁文件。
use TH\Lock\FileFactory; $factory = new FileFactory('/path/to/lock_dir/'); $lock = $factory->create('resource identifier');
聚合锁
如果您想要简化同时获取多个锁的过程,可以使用 \TH\Lock\LockSet
。
use TH\Lock\LockSet; $superLock = new LockSet([$lock1, $lock2, $lock3]); // You can make a set with any types of locks (eg: FileLock, RedisSimpleLock or another nested LockSet) $superLock->acquire(); // all locks will be released when $superLock is destroyed or when `$superLock->release()` is called
它将尝试获取所有锁,如果失败,它将释放已获取的锁,以避免锁定其他进程。
注意:在 LockSet
中放入的 Lock
不再应该手动使用。
注意
分布式系统
在分布式系统中,基于文件的锁定不起作用,您可以使用 php-lock redis 扩展 来获得安全的锁。