当前位置:首页 > PHP > 正文内容

PHP文件锁封装备份代码

高老师5年前 (2021-08-03)PHP1350

备份下代码

<?php

namespace Lib\Library;

use Closure;
use Exception;

/**
 * 文件锁
 * 1.阻塞,进程加锁时发现其他进程已经加锁会一直阻塞等待,一直等到可以加锁成功,然后去执行业务代码
 * 2.非阻塞,进程加锁时发现其他进程已经加锁直接返回,不会执行业务代码
 * 3.注意Erp默认Session驱动为文件,本身请求已经存Session锁机制,所以测试非阻塞时请修改Session驱动为Redis
 * @package Lib\Library
 */
class FileLock
{
    /**
     * 锁文件位置
     * @var string
     */
    private $file;

    /**
     * 锁文件句柄
     * @var
     */
    private $fileHandle;

    /**
     * 构造函数
     * @param string $name 锁名称
     * @throws Exception
     */
    public function __construct($name = 'lock')
    {
        //初始化文件
        $path = RUNTIME_PATH . 'Lock' . DIRECTORY_SEPARATOR;
        $this->file = $path . md5($name);
        if (!is_dir($path)) {
            if (!mkdir($path, 0777, true)) {
                throw new Exception('文件锁目录创建失败,请检查目录' . $path . '是否可写');
            }
        }
        if (!file_exists($this->file)) {
            if (file_put_contents($this->file, '')) {
                throw new Exception('文件锁创建失败,请检查文件' . $this->file . '是否可写');
            }
        }
    }

    /**
     * 加锁
     * @param bool $block
     * @return bool
     */
    public function lock($block = true)
    {
        $this->fileHandle = fopen($this->file, 'r');
        $is_flock = $block ? flock($this->fileHandle, LOCK_EX) : flock($this->fileHandle, LOCK_EX | LOCK_NB);
        if (!$is_flock) {
            fclose($this->fileHandle);
        }
        return $is_flock;
    }

    /**
     * 释放
     */
    public function release()
    {
        if (!$this->fileHandle) {
            return false;
        }
        $unlock = flock($this->fileHandle, LOCK_UN);
        if ($unlock) {
            fclose($this->fileHandle);
            $this->fileHandle = null;
        }
        return $unlock;
    }

    /**
     * 加锁执行
     * @param Closure $func 执行闭包函数
     * @param bool $block 是否阻塞
     * @return mixed 闭包函数的返回值
     */
    public function lockToExecute($func, $block = true)
    {
        $is_flock = $this->lock($block);
        $call_back = null;
        if ($is_flock) {
            $call_back = $func();
            $this->release();
        }
        return $call_back;
    }
}

扫描二维码推送至手机访问。

版权声明:本文由高久峰个人博客发布,如需转载请注明出处。

本文链接:https://blog.20230611.cn/post/209.html

分享给朋友:

“PHP文件锁封装备份代码” 的相关文章

php解决浮点数精度问题

php解决浮点数精度问题

首先看看以下代码:代码1:<?php $a=0.1; $b=0.7; if($a+$b==0.8) { echo "1"; } else{ echo "2"; } ?>代码2:<?php   &n...

php使用swoole扩展推送消息

php使用swoole扩展推送消息

通过http推送消息给socket,socket服务再向客户端推送<?php /*  * Socket推送  * 请用守护进程方式启动php msgservice.php &   (socket只...

redis订阅和发布,redis消息订阅与发布, phpredis订阅和发布

redis订阅和发布,redis消息订阅与发布, phpredis订阅和发布

Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者(publisher),订阅者(subscriber)和频道(channel)。 发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个...

php异步信号处理

php异步信号处理

php7.1引入了PHP异步信号处理函数pcntl_async_signals() 来处理阻塞问题。在php7之前信号处理方式有2种,第一种是基于ticks来每执行一行代码来触发执行信号监听,第二种是直接while(true){  //监听信号 }第一种方式如果某行的代码阻塞时间较长会影响...

php通过event扩展创建定时器,php毫秒级定时器

php通过event扩展创建定时器,php毫秒级定时器

PHP简单定时器可以通过pcntl_signal创建闹钟信号来实现。但是缺点很明显,性能一般,要自己实现守护进程,不支持毫秒级定时器,单进程不支持多个闹钟信号,不能跨平台运行event扩展支持的事件多,性能高。<?php //创建event配置.[空配置] $eventConfig ...

windows安装php event扩展问题

windows安装php event扩展问题

php event扩展在windows中依赖于php_sockets扩展,因此在php.ini中必须先加载php sockets扩展,如下。extension=sockets extension=event...