22

按照this answer限制仅运行一个php脚本的一个实例:

<?php

  $fp = fopen("/tmp/one.txt", "r+");
  if (flock($fp, LOCK_EX)) {
    //
    do_something_lengthy();
    //
    flock($fp, LOCK_UN);
  } else {
    echo "Couldn't get the lock!";
  }

  fclose($fp);

?>

我的问题是,flock如果进程在中间死掉do_something_lengthy(),即在调用之前,'ed one.txt 文件会被解锁flock($fp, LOCK_UN)吗?

4

3 回答 3

18

根据flock()PHP 内部使用flock()的手册页,LOCK_UN当使用fclose().

在脚本终止时,PHP 或操作系统将关闭打开的文件描述符,从而释放您可能拥有的锁。

由于上述行为,本次提交(5.3)和次提交( 5.2)不再在 PHP 本身中进行解锁。

于 2012-11-23T02:17:34.650 回答
6

我做了这个小脚本来测试它

header('Content-type:text/plain; charset=utf-8');

$dir = dirname(__FILE__);
$file = $dir.'/testflock.lock';
$fh = fopen($file, 'w+');

$unlocked = flock($fh, LOCK_EX | LOCK_NB);
echo 'Locked: '.$file.' ';var_dump(!$unlocked);echo PHP_EOL;
if($unlocked){
    sleep(10);
    throw new Exception();
}

对我来说,如果脚本没有抛出任何异常,操作系统在脚本完成执行后大约需要 2-5 秒才能解锁文件,而在脚本由于抛出异常而停止后最多需要 2-5 秒。

请记住,从 php 5.3.2 开始,fclose($fh)将不会解锁文件,并且文件将保持锁定状态,除非您使用 php 将其解锁,否则您将不得不等待操作系统解锁它,如果有一些错误,这可能永远不会发生(这发生在我身上)

要解锁文件:

flock($fh,LOCK_UN);

关闭文件句柄(脚本执行完毕后会自动调用)

fclose($fh);

在没有 的情况下锁定文件LOCK_NB将导致脚本等待文件解锁。

于 2013-09-30T11:39:07.373 回答
2

当脚本完成时,锁会自动释放。但是,您应该手动释放它,而不是依赖于自动失败的发生。最好捕获任何异常,处理它并释放锁。请参阅官方文档 - http://php.net/manual/en/function.flock.php

于 2012-11-23T02:02:19.943 回答