• 技术文章 >后端开发 >PHP问题

    php怎么解决多进程同时写一个文件的问题?

    coldplay.xixicoldplay.xixi2020-07-01 14:15:15原创894

    php解决多进程同时写一个文件的方法:首先复制需要更新的文件,并更改文件名;然后检查最后更新时间和先前所保存的时间是否一致;最后将所修改的临时文件重命名到原文件。


    php解决多进程同时写一个文件的方法:

    首先PHP是支持进程的而不支持多线程(这个先搞清楚了),如果是对于文件操作,其实你只需要给文件加锁就能解决,不需要其它操作,PHP的flock已经帮你搞定了。
    用flock在写文件前先锁上,等写完后解锁,这样就实现了多线程同时读写一个文件避免冲突。大概就是下面这个流程

    /*
    *flock(file,lock,block)
    *file 必需,规定要锁定或释放的已打开的文件
    *lock 必需。规定要使用哪种锁定类型。
    *block 可选。若设置为 1 或 true,则当进行锁定时阻挡其他进程。
    *lock
    *LOCK_SH 要取得共享锁定(读取的程序)
    *LOCK_EX 要取得独占锁定(写入的程序)
    *LOCK_UN 要释放锁定(无论共享或独占)
    *LOCK_NB 如果不希望 flock() 在锁定时堵塞
    /*
    if (flock($file,LOCK_EX))
    {
    fwrite($file,'write more words');
    flock($file,LOCK_UN);
    }
    else
    {
    //处理错误逻辑
    }
    fclose($file);
    )

    相关学习推荐:PHP编程从入门到精通

    方案:不使用flock函数,借用临时文件来解决读写冲突的问题。

    大致原理如下:

    (1)将需要更新的文件考虑一份到我们的临时文件目录,将文件最后修改时间保存到一个变量,并为这个临时文件取一个随机的,不容易重复的文件名。

    (2)当对这个临时文件进行更新后,再检测原文件的最后更新时间和先前所保存的时间是否一致。

    (3)如果最后一次修改时间一致,就将所修改的临时文件重命名到原文件,为了确保文件状态同步更新,所以需要清除一下文件状态。

    (4)但是,如果最后一次修改时间和先前所保存的一致,这说明在这期间,原文件已经被修改过,这时,需要把临时文件删除,然后返回false,说明文件这时有其它进程在进行操作。

    实现代码如下:

    代码如下:

    $dir_fileopen='tmp';
    function randomid(){
        return time().substr(md5(microtime()),0,rand(5,12));
    }
    function cfopen($filename,$mode){
        global $dir_fileopen;
        clearstatcache();
        do{
      $id=md5(randomid(rand(),TRUE));
            $tempfilename=$dir_fileopen.'/'.$id.md5($filename);
        } while(file_exists($tempfilename));
        if(file_exists($filename)){
            $newfile=false;
            copy($filename,$tempfilename);
        }else{
            $newfile=true;
        }
        $fp=fopen($tempfilename,$mode);
        return $fp?array($fp,$filename,$id,@filemtime($filename)):false;
    }
    function cfwrite($fp,$string){
     return fwrite($fp[0],$string);
    }
    function cfclose($fp,$debug='off'){
        global $dir_fileopen;
        $success=fclose($fp[0]);
        clearstatcache();
        $tempfilename=$dir_fileopen.'/'.$fp[2].md5($fp[1]);
        if((@filemtime($fp[1])==$fp[3])||($fp[4]==true&&!file_exists($fp[1]))||$fp[5]==true){
            rename($tempfilename,$fp[1]);
        }else{
            unlink($tempfilename);
      //说明有其它进程 在操作目标文件,当前进程被拒绝
            $success=false;
        }
        return $success;
    }
    $fp=cfopen('lock.txt','a+');
    cfwrite($fp,"welcome to beijing.\n");
    fclose($fp,'on');

    对于上面的代码所使用的函数,需要说明一下:

    (1)rename();重命名一个文件或一个目录,该函数其实更像linux里的mv。更新文件或者目录的路径或名字很方便。但当我在window测试上面代码时,如果新文件名已经存在,会给出一个notice,说当前文件已经存在。但在linux下工作的很好。

    (2)clearstatcache();清除文件的状态.php将缓存所有文件属性信息,以提供更高的性能,但有时,多进程在对文件进行删除或者更新操作时,php没来得及更新缓存里的文件属性,容易导致访问到最后更新时间不是真实的数据。所以这里需要使用该函数对已保存的缓存进行清除。

    以上就是php怎么解决多进程同时写一个文件的问题?的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:php 多进程 文件
    上一篇:php类的静态调用和实例化调用有哪些不同点? 下一篇:PHP支持回调的函数有哪些?
    大前端线上培训班

    相关文章推荐

    • php多进程demo• php多进程插入数据• php多进程处理tcp连接的代码示例• 关于php多进程编程(代码详解)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网