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 ベンチマーク) を使用して、ローカル ホスト 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 に答える