5

我正在尝试在繁忙的站点上模拟文件写入。我编写了以下代码,最终导致计算机冻结。

$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 个,则代码可以正常工作。我该如何应对这种僵局情况?

4

4 回答 4

2

阅读您的代码,我认为您应该flock($handler, LOCK_UN);if (flock($handler, LOCK_EX)) {}条件块内移动。

为了弄清楚到底是什么卡住了,在哪里卡住了,我会在每次调用之前和之后添加带日期戳的(并刷新,所以没有任何东西卡在输出缓冲区中)调试输出,flock()然后将每个脚本实例的输出重定向到自己的文件。fopen()fwrite()fclose()

然后,在冻结 + 重新启动后,您可以查看每个文件的结尾并查看重新启动时每个脚本在做什么。通过比较日期戳,您应该能够看到哪些脚本首先“冻结”。

于 2012-09-07T14:50:12.183 回答
1

在编写更多 php 代码之前,我建议您使用 apache 附带的应用程序 AB(apache benchmark)并在本地主机中模拟高负载 EX>

ab -n 1000 -c 200 http://localhost/your.php

有了这个,您可以模拟 200 个并发用户和 1000 个请求。

于 2011-09-12T15:14:04.697 回答
1

尝试file_put_contents():

<?php

$file = 'file.txt';

$str = "some text\n";

file_put_contents($file, $str, FILE_APPEND | LOCK_EX);

?>

于 2011-04-25T15:10:32.373 回答
0

尝试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。

于 2014-09-08T14:30:40.400 回答