通过首先获取锁来避免PHP代码的并发执行。

4.0.0 2020-01-13 11:12 UTC

This package is auto-updated.

Last update: 2024-09-13 21:10:38 UTC


README

通过首先获取锁来避免PHP代码的并发执行。

Build Status Version

安装

显然是通过Composer

composer require chrisharrison/lock

为什么?

如果你的代码在两个并行处理同时运行时可能会导致不希望出现的竞争条件,你可能想要引入一个锁,以确保只有当一个进程执行该代码时,其他进程才等待。

用法

首先创建一个 LockGuard

$lockGuard = new LockGuard(
    $maxAttempts,
    $attemptIntervalSeconds,
    $lockDriver,
    $lockInspector
);
  • $maxAttempts: int 在放弃前尝试获取锁的最大次数。
  • $attemptIntervalSeconds: int 尝试获取锁之间的秒数。
  • $lockDriver: LockDriver 处理将锁持久化到任何存储机制的类的实例。
  • $lockInspector: LockInspector 处理测试锁有效性的类的实例。

一旦创建了 LockGuard,就可以用它来保护锁内的代码。

$flag = false;

$uniqueProcessId = '<ANY-UNIQUE-STRING>';
$lockUntil = DateTimeImmutable::createFromFormat('U', time()+300); // In 5 mins time

$didExecute = $lockGuard->protect('uniq-process-id', $lockUnitl, function () use (&$flag) {
  $flag = true;
});

上面的代码将尝试将 $flag 设置为 true

如果存在一个尚未过期且不是由同一进程(通过 $uniqueProcessId 识别)创建的锁,则代码将执行,方法将返回 true。否则返回 false。一旦代码成功执行,锁将被释放。即使没有达到 $lockUntil 时间,也会发生这种情况。然而,如果在达到 $lockUntil 时间后代码仍未完成,则锁将过期,其他进程可以再次执行。这是为了减轻锁永远不会释放的情况。

典型用法

$lockPath = 'lock.json';

$maxAttempts = 5;
$attemptIntervalSeconds = 3;
$lockDriver = new FilesystemLockDriver($lockPath);
$lockInspector = new DefaultLockInspector;

$lockGuard = new LockGuard(
    $maxAttempts,
    $attemptIntervalSeconds,
    $lockDriver,
    $lockInspector
);

FilesystemLockDriver 将锁作为JSON持久化到本地文件系统中的文件。你可以创建其他使用其他方法的 LockDriver,例如使用 FlySystem 利用S3。