PHP单机文件排队锁
文章介绍了一个PHP类`Locker`,用于实现文件锁机制以防止并发冲突。该类提供获取(`wait`)、释放(`release`)和检查(`isLocked`)锁的方法,并支持超时设置与自动资源清理。
2025-8-4 01:18:28
Author: www.yanglong.pro(查看原文)
阅读量:22
收藏
class Locker
{
private static array $lockers = [];
/**
* 获取锁
* @param string $key 锁的唯一标识
* @param int $timeout 超时时间(秒),0表示无限等待
* @return bool 是否获取到锁
*/
public static function wait(string $key, int $timeout = 0): bool
{
$file = sys_get_temp_dir() . "/.lock_" . md5($key) . ".tmp";
$start_time = time();
while (true) {
// 检查是否超时
if ($timeout > 0 && (time() - $start_time) >= $timeout) {
return false;
}
// 尝试打开文件
$fp = @fopen($file, "c+");
if (!$fp) {
usleep(10000); // 等待10毫秒
continue;
}
// 尝试获取锁
if (flock($fp, LOCK_EX | LOCK_NB)) {
// 获取锁成功
self::$lockers[$key] = $fp;
return true;
} else {
// 获取锁失败,关闭文件句柄
fclose($fp);
usleep(10000); // 等待10毫秒后重试
}
}
}
/**
* 释放锁
* @param string $key 锁的唯一标识
* @return bool 是否成功释放
*/
public static function release(string $key): bool
{
if (!isset(self::$lockers[$key])) {
return false;
}
$fp = self::$lockers[$key];
if (is_resource($fp)) {
flock($fp, LOCK_UN); // 释放文件锁
fclose($fp); // 关闭文件句柄
}
unset(self::$lockers[$key]);
return true;
}
/**
* 检查是否持有某个锁
* @param string $key 锁的唯一标识
* @return bool 是否持有锁
*/
public static function isLocked(string $key): bool
{
return isset(self::$lockers[$key]) && is_resource(self::$lockers[$key]);
}
/**
* 析构时释放所有锁
*/
public function __destruct()
{
foreach (array_keys(self::$lockers) as $key) {
self::release($key);
}
}
}
使用:
if (!Locker::wait(md5("key"), 3)) {
recordlog("3秒内获取不到锁返回提示 请勿重复请求 ");
# 3秒内获取不到锁返回提示
exit_json(0, '请勿重复请求');
}
文章来源: https://www.yanglong.pro/php%e5%8d%95%e6%9c%ba%e6%96%87%e4%bb%b6%e6%8e%92%e9%98%9f%e9%94%81/
如有侵权请联系:admin#unsafe.sh