? PHP は同時実行環境でどのようにファイルを書き込むべきですか?実際、この問題は PHP だけが直面している問題ではありません。スレッドであってもプロセスであっても、同時に書き込みを行うと、共有リソースの書き込み競合が発生します。ソフトウェア開発のプロセスでは、共有変数を書き込むマルチスレッド、データを同時に書き込むデータベースへの複数の接続、ファイルを書き込む複数のプロセスなど、書き込み競合があらゆる場所で発生します。では、これらにどう対処すればよいのでしょうか?現在の一般的な解決策は、共有リソースに排他ロック (書き込みロック) を適用することです。
? ? PHP では、その名のとおり、ファイルロック操作関数を提供しました。ファイル ロック メカニズムはホスト ファイル システムに依存します。つまり、Flock は、ファイル システムのロック メカニズムを呼び出すシェル関数にすぎません。
? ? ロックは読み取りロックと書き込みロックの 2 種類に分けられます。書き込みロックは排他ロックや排他ロックとも呼ばれます。これは、1 つのスレッドまたはプロセスがリソースを排他的に占有し、他のスレッドまたはプロセスがそのリソースを使用できないようにすることを意味し、データの書き込みが干渉されたり競合したりしないようにします。読み取りロックは共有ロックとも呼ばれます。 。これにより、複数のスレッドまたはプロセスが同時に読み取りを行うことができますが、書き込みはできません。
関数プロトタイプ:
?
<?php> flock ($handle, $operation, &$wouldblock = null); <?>
?
パラメータの説明:
$handle //ファイル ポインタ
$operation //ロックタイプ
$operation にはいくつかの使用可能な値があります: LOCK_EX [書き込みロック]、LOCK_SH [読み取りロック]、LOCK_UN [解放ロック]
? 例を見てみましょう。
?? ? ? Jmeter を使用して同時実行テストを実行すると、(Apache または nginx のパフォーマンスのボトルネックに関係なく) ファイル内に 3000 行があることがわかります。
<?php> function fileWrite($file) { $fp = fopen($file, 'a'); flock($fp, LOCK_EX);//上写锁 /*写数据*/ fwrite($fp, "1"); fwrite($fp, "2"); fwrite($fp, "3\r\n"); flock($fp, LOCK_UN);//释放锁 fclose($fp); } fileWrite('D:/txt.txt'); <?>
? ? Jmeter を使用して同時実行テストを行う場合、このファイルをメモ帳で開き、何かを変更してから [保存] をクリックすると、次のような状況になります。
? これは、ファイルがロックされており、メモ帳プロセスが書き込みできないためです。
? ? 前述したように、flock 関数のロック メカニズムは、PHP によってはサポートされていないファイル システムのロック メカニズムをカプセル化します。マニュアルに記載されているように、FAT や NTF などの古いファイル システムやネットワーク ファイル システムは flock ではサポートされていません。私自身はテストしていません。
? ? PHP マニュアルには、flock はプロセス レベルであり、マルチスレッドでは機能しないと記載されています。おそらく誰もが混乱していると思いますが、PHP にはスレッドの概念がありません。マルチスレッドをサポートするサーバーに PHP を置くのはどうでしょうか?テストを受けてください。
このステップを分析すると、flock がホストに依存し、環境に要件があることがわかります。これにより、コードの移植性が大きく損なわれます。怖がった! !心配しないでください、実際には被害はそれほど深くなく、群れはまだほとんどの環境を満足させることができます。
?
? ? flock の移植性の欠如のため、私も注目し始めたところ、次のようなコードがインターネット上で流通しているのを発見しました。
?
このコードにはロック効果があると思いますか? ?テストしてみよう! !実際には、一見してロックする必要はありません。
file_exists は、2 つのプロセスが同時に実行されると、いわゆるロックされていると判断されます。ファイルは存在しないため、結果は競合しません。<?php> function fileWrite($file,$content) { $lock = $file.'.lock'; while (true) { if (file_exists($lock)) { usleep(100); } else { touch($lock);//上锁 file_put_contents($file, $content, FILE_APPEND);//写文件 @unlink($lock);//删除锁 break; } } } fileWrite('D:/txt.txt','i m a phper'); <?>
Lock は実際には同時アクセス キューのブロックをシリアル化してから、アクセスを順番に処理します。上記のコードにはキューさえありません。では、どのようにしてロックできるのでしょうか。
? このとき、複数のプロセスが同時に flock を実行するのは並列ではないでしょうか?はい、flock は並行して実行されます。これは、flock のロックの適用が並行してホスト ファイル システムを調整することを意味するため、ロック リクエストは自然に処理のためにキューに入れられます。
?