【发布时间】:2010-11-15 15:10:17
【问题描述】:
我有两个不同的 PHP 文件,它们都写入同一个文件。每个 PHP 脚本由两个不同 HTML 页面的用户操作调用。我知道可以调用两个 PHP 文件,但是两个 PHP 文件会同时尝试写入文件吗?如果是,会发生什么?此外,可以使其中一个 PHP 正常失败(文件写入将失败,而另一个 PHP 可以写入文件),因为一个 PHP 函数不如另一个函数重要。
【问题讨论】:
我有两个不同的 PHP 文件,它们都写入同一个文件。每个 PHP 脚本由两个不同 HTML 页面的用户操作调用。我知道可以调用两个 PHP 文件,但是两个 PHP 文件会同时尝试写入文件吗?如果是,会发生什么?此外,可以使其中一个 PHP 正常失败(文件写入将失败,而另一个 PHP 可以写入文件),因为一个 PHP 函数不如另一个函数重要。
【问题讨论】:
解决这个问题的常用方法是让两个脚本都使用flock() 进行锁定:
$f = fopen('some_file', 'a');
flock($f, LOCK_EX);
fwrite($f, "some_line\n");
flock($f, LOCK_UN);
fclose($f);
这将导致脚本在写入文件之前相互等待完成文件。如果您愿意,“不太重要”的脚本可以这样做:
$f = fopen('some_file', 'a');
if(flock($f, LOCK_EX | LOCK_NB)) {
fwrite($f, "some_line\n");
flock($f, LOCK_UN);
}
fclose($f);
这样如果它发现某个文件正忙于处理文件,它就不会做任何事情。
【讨论】:
如果文件以追加方式打开,请注意 posix 声明原子访问。这意味着您可以使用多个线程附加到文件中,并且它们的行不会被损坏。
我确实用十几个线程和几十万行对此进行了测试。没有一行被损坏。
这可能不适用于超过 1kB 的字符串,因为缓冲区大小可能会超出。
这也可能不适用于不符合 posix 的 Windows。
【讨论】:
请注意:
从 PHP 5.3.2 开始,文件资源句柄关闭时的自动解锁被移除。 现在必须手动解锁。
更新后的向后兼容代码为:
if (($fp = fopen('locked_file', 'ab')) !== FALSE) {
if (flock($fp, LOCK_EX) === TRUE) {
fwrite($fp, "Write something here\n");
flock($fp, LOCK_UN);
}
fclose($fp);
}
即你必须显式调用flock(.., LOCK_UN) 因为fclose() 不再这样做了。
【讨论】:
看看flock函数。
【讨论】:
仅供参考:flock 仅适用于 *nix,不适用于 Windows
【讨论】: