【问题标题】:php flock behaviour when file is locked by one process当文件被一个进程锁定时的php群行为
【发布时间】:2013-09-20 22:09:53
【问题描述】:

让我们考虑一个通过用户输入删除一行的示例 php 脚本:

$DELETE_LINE = $_GET['line'];
$out = array();
$data = @file("foo.txt");
if($data)
{
    foreach($data as $line)
        if(trim($line) != $DELETE_LINE)
            $out[] = $line;
}
$fp = fopen("foo.txt", "w+");
flock($fp, LOCK_EX);
foreach($out as $line)
    fwrite($fp, $line);
flock($fp, LOCK_UN);
fclose($fp); 

我想知道当前是否有用户正在执行这个脚本,并且文件“foo.txt”在执行完成的同时或之前被锁定,如果其他用户调用了这个脚本,会发生什么? 第二个用户进程会等待第一个用户解锁文件吗?或者第二个用户输入的行删除会失败?

【问题讨论】:

    标签: php


    【解决方案1】:

    如果您在另一个进程锁定文件时尝试获取排他锁,您的尝试将等到文件解锁。这就是锁定的重点。

    请参阅flock() 的 Linux 文档,该文档描述了它在操作系统中的一般工作方式。 PHP 在后台使用fcntl(),因此通常支持 NFS 共享。

    没有超时。如果你想自己实现超时,你可以这样做:

    $count = 0;
    $timeout_secs = 10; //number of seconds of timeout
    $got_lock = true;
    while (!flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
        if ($wouldblock && $count++ < $timeout_secs) {
            sleep(1);
        } else {
            $got_lock = false;
            break;
        }
    }
    if ($got_lock) {
        // Do stuff with file
    }
    

    【讨论】:

    • 这意味着,另一个进程将等待前一个进程解锁文件。我想知道另一个进程将等待解锁文件多长时间?有没有超时?
    • 没有超时。我添加了代码以使用非阻塞选项实现超时。
    • 请注意,LOCK_NB$wouldblock 参数在 Windows 上不受支持,根据 PHP 文档:ca1.php.net/manual/en/function.flock.php 如果您无法控制哪些服务器将运行您的软件,那么你也不能实际使用上面的代码。在这种情况下,在我看来,根本就没有办法实现任何形式的“锁定超时”。
    • 在使用这种技术时请记住,请求锁的不同进程不会排在严格的队列中。每次进程进入sleep()阶段,都会跳出队列,休眠后回到队列的末尾。这对您的应用程序来说可能没问题,但这只是意味着无法保证每个进程必须等待多长时间以及它们将按什么顺序运行。
    • 需要注意的是,如果在等待锁的过程中超过了最大脚本执行时间,进程将终止。这是开箱即用的最明确的超时。
    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2021-03-19
    相关资源
    最近更新 更多