flock()関数は、最初のパラメーターとしてファイルハンドルを取り、2番目のパラメーターとしてロック操作を取ります。すでに知っているファイルハンドルであり、操作は簡単です。LOCK_SHは共有ロックを要求し、LOCK_EXは排他ロックを要求し、LOCK_UNはロックを解放します。flock()を呼び出すと、ファイルロックが正常に取得された場合はtrueが返され、失敗した場合はfalseが返されます。したがって、たとえば、flock()は次のように使用できます。
<?php
$fp = fopen( $filename,"w"); // open it for WRITING ("w")
if (flock($fp, LOCK_EX)) {
// do your file writes here
flock($fp, LOCK_UN); // unlock the file
} else {
// flock() returned false, no lock obtained
print "Could not lock $filename!\n";
}
?>
PHPのファイルロックメカニズムは、デフォルトでプロセスを自動的にロックのためにキューに入れます。たとえば、次のスクリプトをflock.phpとして保存します。
<?php
$fp = fopen("foo.txt", "w");
if (flock($fp, LOCK_EX)) {
print "Got lock!\n";
sleep(10);
flock($fp, LOCK_UN);
}
?>
そのスクリプトはファイルfoo.txtをロックしようとするため、そのファイルを作成する必要があります。スクリプトはそれをLOCK_EXでロックします。これは、他のプログラムがそのファイルをロックできないことを意味します。ロックが取得されると、スクリプトは10秒間スリープし、ファイルのロックを解除して終了します。別のアプリケーションにロックがあるためにロックを取得できない場合、スクリプトはflock()呼び出しでロックが解放されるのを待ってから、それ自体をロックして続行します。
これをテストするには、2つのコマンドプロンプトを開き、スクリプトを2回実行します。最初に実行されたスクリプトはすぐにロックを取得し、「Got lock!」と出力してから、10秒間スリープします。最初のスクリプトがスリープしているときに2番目のスクリプトを起動すると、flock()呼び出しを待機(「ブロック」)し、最初のスクリプトが終了するのを待ちます。最初のスクリプトが終了すると、2番目のスクリプトはロックの取得に成功し、「ロックを取得しました!」と出力します。その後、最終的に終了するまでさらに10秒間スリープします。
ファイルのロックが解除されるのをスクリプトで待機させることが望ましくない場合があります。この場合、ビット単位のOR演算子|を使用して2番目のパラメーターにオプションを追加できます。LOCK_NB ORedを通常の2番目のパラメーターと一緒に渡すと、PHPはファイルロックを要求するときにブロックしません。これは、ファイルロックが使用できない場合、flock()は、ロックが使用可能になるのを待つのではなく、falseですぐに戻ることを意味します。
これがコードでどのように見えるかです:
<?php
$fp = fopen("foo.txt", "w");
if (flock($fp, LOCK_EX | LOCK_NB)) {
echo "Got lock!\n";
sleep(10);
flock($fp, LOCK_UN);
} else {
print "Could not get lock!\n";
}
?>
今回は、最初のスクリプトがロックを取得して「Got lock!」と出力しますが、2番目のスクリプトはロックを取得できず、すぐに戻って「Could not getlock!」と出力します。