我正在尝试模拟繁忙网站上的文件写入。我写了下面的代码,最终冻结了计算机。
$loop = 10000;
$sleep = 500000;
$i =0;
while($i < $loop) {
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
$handler = fopen($file,"a+");
if($handler) {
if (flock($handler, LOCK_EX)) {
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = ($endtime - $starttime);
fwrite($handler,"Script 1 took $totaltime secs\n");
}
flock($handler, LOCK_UN);
fclose($handler);
}
$i++;
usleep($sleep);
}
我无法使用LOCK_NB,因为它无法在Windows上运行。如果少于13个进程同时执行上述代码,则代码可以正常工作。我该如何应对这种僵局?
答案 0 :(得分:2)
阅读你的代码,我想你应该移动“flock($ handler,LOCK_UN);”在“if(flock($ handler,LOCK_EX)){}”条件块内。
要确切地知道卡在哪里以及在哪里,我会在每次调用flock(),fopen(),fwrite()之前和之后添加datestamped(并刷新,因此没有任何东西卡在输出缓冲区中)调试输出和fclose(),并将每个脚本实例的输出重定向到自己的文件。
然后,在冻结+重启后,您可以查看每个文件的结尾,并查看每个脚本在重新启动时正在执行的操作。通过比较日期戳,您应该能够看到哪个脚本首先“冻结”。
答案 1 :(得分:1)
HY
尝试使用file_put_contents():
<?php
$file = 'file.txt';
$str = "some text\n";
file_put_contents($file, $str, FILE_APPEND | LOCK_EX);
?>
答案 2 :(得分:1)
在您编写更多PHP代码之前,我建议您使用apache附带的应用程序AB(apache基准测试)并在本地主机EX中模拟高负载&gt;
ab -n 1000 -c 200 http://localhost/your.php
通过此功能,您可以模拟200个并发用户和1000个请求。
答案 3 :(得分:0)
尝试&#34;守卫&#34; LOCK_EX
具有额外的mkdir()
锁定机制,如下所述:
https://stackoverflow.com/a/7927642/318765
示例:
<?php
$file = 'deadlock.txt';
$loop = 10000;
$sleep = 500000;
$i = 0;
while ($i < $loop) {
$starttime = microtime(true);
$handler = fopen($file, 'a+');
if ($handler) {
if (!file_exists($file . '_lock')) {
if (mkdir($file . '_lock')) {
if (flock($handler, LOCK_EX)) {
$endtime = microtime(true);
$totaltime = ($endtime - $starttime);
$totaltime = number_format($endtime - $starttime, 10);
if ($totaltime > 1) {
break;
}
}
flock($handler, LOCK_UN);
fclose($handler);
rmdir($file . '_lock');
}
}
}
$i++;
usleep($sleep);
}
?>
如您所见,我添加了break;
以避免死锁。如果脚本停止,您可以查看日志文件。
在Linux中,我使用这个mkdir()
技巧而没有flock()
因为它是原子的。我也不知道这是否适用于Windows。