繁体   English   中英

flock(LOCK_SH / LOCK_EX)时,PHP脚本文件会无限期加载到浏览器中

[英]PHP script file loads indefinitely on browser when flock (LOCK_SH/LOCK_EX)

我在尝试学习如何锁定文件以防止脚本在另一个文件写入时读取文件或两个脚本同时写入同一文件的过程中遇到了此链接

我创建了两个脚本readandwritelock.phpreadlock.php ,第一个脚本使用file_get_contents检索文件,追加该脚本,然后使用file_put_contents($file, $data, LOCK_EX)写回到同一文件,第二个脚本在flock($file, LOCK_SH)之后检索具有file_get_contents flock($file, LOCK_SH)

<?php
    //readandwritelock.php

    $myfile = fopen('15-11-2018.txt', 'r+');
    if (flock($myfile, LOCK_SH)) {

        echo "Gotten lock<br>";
        $current = file_get_contents('15-11-2018.txt');

        /*I commented this on my second test to see if file_put_contents will work.
        After uncommenting and third test, it does not work anymore.

        if (flock($myfile, LOCK_UN)) {

            echo "Unlocked<br>";
        }*/

        $current .= "appending";

        if (file_put_contents('15-11-2018.txt', $current, LOCK_EX)) {
            echo "Success";
        }
        else {
            echo "Failed";
            //browser loads indefinitely so this does not run
        }

        fclose($myfile);
    }
?>

我面临的问题是,获得锁后,我第一次尝试file_get_contents ,然后释放了锁,然后继续追加和file_put_contents($file, $data, LOCK_EX) 但是,在第二次尝试中,我决定评论一下LOCK_SH锁的释放以进行测试,看看会发生什么。 该脚本文件在浏览器中无限期加载(正在等待localhost ...),因此我第三次尝试恢复了所做的更改,但是这次脚本文件仍然无限期加载。 好像从未释放过LOCK_SH

我一定做错了,但我不知道到底是什么。 有人可以解释吗?

这已经在XAMPP和macOS High Sierra和Chrome上进行了测试。

<?php
    //readlock.php
    //works as normal
    $myfile = fopen('15-11-2018.txt', 'r');

    if (flock($myfile, LOCK_SH)) {

        echo "Gotten lock<br>";
        $current = file_get_contents('15-11-2018.txt');
        echo $current;

        if (flock($myfile, LOCK_UN)) {
            echo "<br>Unlocked";
        }
        fclose($myfile);
    }
?>

您的浏览器似乎无限期加载的原因是因为您的PHP文件从未完成。

首先,您将获得文件的LOCK_SH(共享或读取锁定),这在读取内容时很好。 问题是您还尝试在file_put_contents函数中的同一文件上获得LOCK_EX(排他锁)。 因此,file_put_contents函数将阻塞,直到所有其他锁(共享和独占锁)都被解锁为止,这是行不通的(这是一个死锁)。

为了使代码正常工作,您可以首先尝试获取排他锁

if( flock($myfile, LOCK_EX) ) {
    // ...

或者您在写之前解锁共享锁

flock($myfile, LOCK_UN);
if ( file_put_contents('15-11-2018.txt', $current, LOCK_EX) ) {
    // ...

通常,最好使锁的寿命尽可能短。 如果您打算在读写之间对数据进行大量操作,建议您在读取后立即解锁文件,然后再次锁定以进行写入。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM