在 ThinkPHP 6 控制器中使用文件锁机制
- 创建锁管理类
首先,创建一个锁管理类来处理文件锁:
namespace app\common\service;
use Exception;
class LockManager
{
private $lockFilePath;
private $lockFile;
public function __construct($lockFilePath)
{
$this->lockFilePath = $lockFilePath;
}
public function __destruct()
{
$this->releaseLock();
}
public function executeWithLock(callable $callback)
{
// 打开锁文件,文件不存在时会自动创建
$this->lockFile = fopen($this->lockFilePath, 'w+');
if (!$this->lockFile) {
throw new Exception("无法打开锁文件");
}
try {
// 尝试获取排他锁(独占锁)
if (flock($this->lockFile, LOCK_EX)) {
// 锁定成功后执行关键代码
$callback();
} else {
throw new Exception("无法获取锁");
}
} finally {
// 释放锁
$this->releaseLock();
}
}
private function releaseLock()
{
if ($this->lockFile) {
flock($this->lockFile, LOCK_UN);
fclose($this->lockFile);
}
}
}
- 在控制器中使用锁
在你的控制器中,调用 LockManager
来执行需要加锁的操作:
namespace app\controller;
use app\common\service\LockManager;
use think\Controller;
use think\Request;
class TaskController extends Controller
{
public function process(Request $request)
{
// 定义锁文件的路径
$lockFilePath = runtime_path() . 'lockfile';
// 创建 LockManager 实例
$lockManager = new LockManager($lockFilePath);
// 执行需要加锁的操作
try {
$lockManager->executeWithLock(function() {
// 执行关键操作
echo "获取锁成功,执行关键操作\n";
// 模拟长时间操作
sleep(5);
echo "操作完成,释放锁\n";
});
} catch (Exception $e) {
// 处理异常
echo "错误: " . $e->getMessage();
}
}
}
在服务层中使用锁
如果你希望在服务层中处理锁,可以将锁管理逻辑集成到服务类中,类似于控制器中的使用方式。然后在控制器中调用这个服务来处理业务逻辑。
总结
- 将锁管理逻辑封装到服务类中。
- 在需要加锁的地方(控制器、服务层等)创建
LockManager
实例并调用executeWithLock
方法来执行需要加锁的操作。
这样,可以确保在执行关键操作时获得独占锁,并在操作完成后释放锁。