6

私は Java、C、および C++ に精通しています。これらの言語では、常に 1 つのスレッドのみがリソースにアクセスするように制御する方法があります。今、似たようなものを探していますが、PHP 5.x.

1つの例で私の問題を定式化するには:

ページロードカウンターの値である数値のみを格納するASCIIファイルがあります。アプリケーションの展開時に、ファイルは単純に 0 を保持します。アクセスごとに値が 1 ずつ増加します。目標は、ページの読み込みを追跡することです。

問題は、多くのユーザーがカウンターを含むページに同時にアクセスしている場合に発生します。スレッド A が現在の値を読み取ったとき、それが 11 だとしましょう。別のスレッド B が値を読み取りますが、まだ 11 です。次に、最初のスレッド A が読み取り値をインクリメントし、ファイルに 12 を書き込み、ファイルを閉じます。次に、2 番目のスレッド B が、11 だった読み取り値をインクリメントし、12 を取得して、それをファイルに書き込みます。値 12 がファイルに保存されますが、実際には 13 である必要があります。

別のプログラミング言語では、ミューテックスを使用してこれを解決していたでしょう。モジュールの一部として、ミューテックス、共有メモリ、およびその他の機能があることを理解しています。しかし、「ほとんどのサーバー」で機能するソリューションが欲しいです。プラットフォームに依存しません。ほとんどの安価な Web ホストにインストールされています。この問題の良い解決策はありますか? データベースを使用できない場合、どの方法を使用しますか?

4

2 に答える 2

7

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);
}

?>
于 2008-10-08T22:45:21.423 に答える
3

PHP の flock() 関数がそのルートです。ただし、最初に flock() を呼び出して、ファイルへのすべてのアクセスが保護されていることを確認する必要があります。明示的に呼び出しを行わない限り、PHP はファイルがロックされているかどうかをチェックしません。

概念は実質的にミューテックス (共有リソースの保護など) と同じですが、特に強調するほど重要です。

于 2008-10-08T22:51:57.043 に答える