PHP 5.x同期ファイルアクセス(データベースなし)
-
06-07-2019 - |
質問
私はJava、C、C ++に精通しており、特定の時点で1つのスレッドのみがリソースにアクセスするように制御する方法があります。今は似たようなものを探していますが、PHP 5.xを使用しています。
1つの例で問題を定式化するには:
ページロードカウンタの値である数値のみを保存するASCIIファイルがあります。アプリケーションの展開時に、ファイルは単に0を保持します。アクセスごとに値が1ずつ増加します。目標は、ページの読み込みを追跡することです。
この問題は、カウンターを含むページに多くのユーザーが同時にアクセスしている場合に発生します。スレッドAが現在の値を読み取り、11とすると、Bと呼ばれる別のスレッドが値を読み取ります。まだ11です。その後、最初のスレッドAは読み取り値をインクリメントし、ファイルに12を書き込み、閉じます。次に、2番目のスレッドBが読み取り値をインクリメントします。これは11でしたが、12を取得してファイルに書き込みます。値12はファイルに保存されますが、実際には13でなければなりませんでした。
別のプログラミング言語では、ミューテックスを使用してこれを解決していました。モジュールの一部として、ミューテックス、共有メモリ、その他の機能があることを理解しています。しかし、「ほとんどのサーバー」で動作するソリューションが欲しいです。そこに。プラットフォームに依存しません。最も安価なWebホストにインストールされます。この問題の解決策はありますか?存在しない場合、データベースを使用することはオプションではない場合、どの方法を使用しますか?
解決
PHPのflockのバリアントを試すことができます( http://www.php.net/flock )
似たようなものを想定します(これは、ファイル/tmp/counter.txtが既に存在し、ファイル内にカウンターがあることを前提としています):
<?php
$fp = fopen("/tmp/counter.txt", "r+");
echo "Attempt to lock\n";
if (flock($fp, LOCK_EX)) {
echo "Locked\n";
// Read current value of the counter and increment
$cntr = fread($fp, 80);
$cntr = intval($cntr) + 1;
// Pause to prove that race condition doesn't exist
sleep(5);
// Write new value to the file
ftruncate($fp, 0);
fseek($fp, 0, SEEK_SET);
fwrite($fp, $cntr);
flock($fp, LOCK_UN); // release the lock
fclose($fp);
}
?>
他のヒント
PHPのflock()関数は、進むべき道です。ただし、ファイルへの all アクセスは、最初にflock()を呼び出して保護する必要があります。 PHPは、明示的に呼び出しを行わない限り、ファイルがロックされているかどうかをチェックしません。
この概念は、ミューテックス(共有リソースの保護など)とほぼ同じですが、特別な強調を行うには十分に重要です。