27

PHP でのロックに関するテキストを読んでください。
それらはすべて、主にhttp://php.net/manual/en/function.flock.phpに向けられています。

このページでは、ハードディスク上のファイルを開く方法について説明します!!

本当にそうですか?つまり、これはロックを非常に高価にします-つまり、ロックするたびにハードディスクにアクセスする必要があります )=

嬉しいニュースでもう私を慰めることができますか?

編集:

私がここで得たいくつかの返信のために、私はこれを尋ねたいと思います;
私のスクリプトは 1 つのスレッドだけで実行されますか、それとも複数のスレッドで実行されますか? それが1つの場合、明らかにミューテックスは必要ないからです。簡潔な答えはありますか?

私は正確に何をしようとしていますか

ircmaxell からの質問。
これは話です:

私は 2 つの ftp サーバーを持っています。オンライン ユーザーの数を自分の Web サイトに表示できるようにしたいと考えています。
したがって、これらの ftp サーバーは統計情報を特定の PHP スクリプト ページに「POST」すると考えました。このページの URL を「http://mydomain.com/update.php」とします。

Web サイトのメイン ページ (" http://mydomain.com/index.php ") で、累積統計 (オンライン ユーザー) を表示します。

それでおしまい。

私の問題は、ある ftp サーバーが自分の統計を更新している間に別の ftp サーバーが更新した場合、情報が混ざり合うかどうかわからないことです。
マルチスレッドのときのように。2 つのスレッドが同時にいくつかの「int」変数を増やします。それらの間で同期しない限り、期待どおりには起こりません。
それで、私は問題がありますか?そうですね?

考えられる解決策

一日中一生懸命考えていると、ここにアイデアがあります。あなたの意見を聞かせてください。
前述のように、これらの ftp サーバーは 60 秒ごとに統計を投稿します。
このファイル「stats.php」を持つことを考えています。
これは、ftp サーバーがアクセスする更新スクリプト (「update.php」) と、訪問者がオンラインのユーザー数を確認できる「index.php」ページに含まれます。
これで、ftp サーバーが更新されると、「update.php」のスクリプトが「stats.php」を新しい累積統計で変更します。
最初に「stats.php」に含まれる統計を読み取り、蓄積し、そのファイルを書き換えます。

私が間違っていなければ、PHP はファイル ("stats.php") が変更されたことを検出し、新しいファイルをロードします。正しい?

4

5 に答える 5

33

ええと、ほとんどのPHPは異なるプロセススペースで実行されます(スレッドの実装はほとんどありません)。簡単なのは群れです。すべてのプラットフォームで動作することが保証されています。

ただし、サポートでコンパイルする場合は、Semaphore拡張機能などの他のいくつかのものを使用できます。(PHPを--enable-sysvsemでコンパイルします)。次に、次のようなことを行うことができます(sem_acquire()はブロックする必要があります。ただし、何らかの理由でブロックできない場合は、falseが返されます):

$sem = sem_get(1234, 1);
if (sem_acquire($sem)) {
    //successful lock, go ahead
    sem_release($sem);
} else {
    //Something went wrong...
}

あなたが持っている他のオプションは、MySQLユーザーレベルのロック GET_LOCK('name', 'timeout')、またはAPCやXCacheのようなものを使用して独自のものを作成することです(他の誰かがあなたのチェックの間にロックを取得する競合状態が作成される可能性があるため、これは本当のロックではないことに注意してくださいおよびロックの受け入れ)。

編集:編集した質問に答えるには:

それはすべてサーバー構成によって異なります。PHPは、マルチスレッドで実行することも(各リクエストが異なるスレッドで処理される場合)、マルチプロセスで実行することもできます(各リクエストが異なるプロセスで処理される場合)。それはすべてあなたのサーバー構成に依存します...

PHPがすべてのリクエストをシリアルに処理し、1つのプロセス(および1つのスレッド)のみがすべてのリクエストを処理することは非常にまれです。CGIを使用している場合、デフォルトではマルチプロセスです。FastCGIを使用している場合は、マルチプロセスおよびマルチスレッドである可能性があります。Apacheでmod_phpを使用している場合は、ワーカーの種類によって異なります。

  1. mpm_workerはマルチプロセスとマルチスレッドの両方になり、プロセスの数はServerLimit変数によって指定されます。
  2. プリフォークはマルチプロセスになります
  3. パーチャイルドもマルチプロセスになります

編集:2番目に編集された質問に答えるには:

とても簡単です。ファイルに保存します。

function readStatus() {
    $f = fopen('/path/to/myfile', 'r');
    if (!$f) return false;
    if (flock($f, LOCK_SH)) {
        $ret = fread($f, 8192);
        flock($f, LOCK_UN);
        fclose($f);
        return $ret;
    }
    fclose($f);
    return false;
}

function updateStatus($new) {
    $f = fopen('/path/to/myfile', 'w');
    if (!$f) return false;
    if (flock($f, LOCK_EX)) {
        ftruncate($f, 0);
        fwrite($f, $new);
        flock($f, LOCK_UN);
        fclose($f);
        return true;
    }
    fclose($f);
    return false;
}

function incrementStatus() {
    $f = fopen('/path/to/myfile', 'rw');
    if (!$f) return false;
    if (flock($f, LOCK_EX)) {
        $current = fread($f, 8192);
        $current++;
        ftruncate($f, 0);
        fwrite($f, $current);
        flock($f, LOCK_UN);
        fclose($f);
        return true;
    }
    fclose($f);
    return false;
}
于 2010-05-27T13:39:33.363 に答える
1

問題は、FTP サーバーが POST で update.php ファイルにプッシュしている統計情報をどこに保存するかということです。ローカル ファイルの場合は、2 番目の投稿で ircmaxell から回答がありました。これは、ミューテックス (セマフォ関数) でも行うことができます。別の解決策は、MySQL MyISAM テーブルを使用して統計を保存し、update info_table set value = value + 1. テーブルをロックし、リクエストをシリアル化する必要があり、問題はありません。

于 2011-02-23T13:03:28.203 に答える
0

はい、それは本当です。PHPはApacheによって実行され、Apacheは実行スレッドを最適と見なすように編成できます(さまざまなワーカーモデルを参照)。したがって、一度に1つずつリソースにアクセスする場合は、ファイルにロックするか(たとえば、cronジョブを処理する場合に適しています)、データベーストランザクションメカニズム、ACID機能、およびデータベースリソースのロックに依存します。データを扱っている場合。

于 2010-05-27T13:39:14.880 に答える
-4

PHP はマルチスレッドをサポートしていません。すべてのリクエスト (したがって、すべての PHP スクリプト) は 1 つのスレッド (または、PHP の実行方法によってはプロセス) でのみ実行されます。

于 2010-05-27T13:37:24.913 に答える