我的问题是:即使写操作使用排他锁,在读取期间不能使用共享锁会导致写入错误吗?
假设我想创建一个基于文件的计数器,如下所示:
//increment counter by 1
$fp = fopen($path, 'r+b');
if (flock($fp, LOCK_EX)) {
//read
fseek($fp, 0, SEEK_END);
$size = ftell($fp);
fseek($fp, 0, SEEK_SET);
if ($size == 0) {
$counter = 0;
} else {
$data = fread($fp, $size);
$counter = intval($data);
}
//do something with data we just read
$counter ++;
//write
fseek($fp, 0, SEEK_SET);
ftruncate($fp, 0);
fwrite($fp, $counter);
fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
} else {
fclose($fp);
throw new Exception("Lock failed");
}
现在我想在其他地方展示它:
echo intval(file_get_contents($path));
注意file_get_contents
不使用共享锁。
该代码已被证明在页面负载过重的情况下会损坏数据,即计数器被重置几次回到 0。
我更改了要使用的代码,fopen
现在LOCK_SH
看起来还可以,但我无法确认这确实是问题的根源,因为我无法控制负载。使用多个 CLI PHP 实例本地执行上述代码表明代码甚至可以使用file_get_contents
...