ファイルをロックする(flock)

広告

ファイルを読んだり書き込んだりする時に、他の人が同時にそのファイルに何か行おうとすると問題が起きる事があります。その為、ファイルに対する処理を行う前にファイルをロックして、作業中は他の人がそのファイルに作業を行えないようにする必要があります。

ファイルに対するロックを行うにはflock関数を利用します。

ファイルをロックします。対象となるハンドルはfopenなどで取得したハン
ドルを指定します。

引数:
  handle  対象となるファイルのハンドル
  operation  ロックの方法
返り値:
  成功した場合に TRUE、失敗した場合に FALSE

ロックの方法は下記の通りです。

説明
LOCK_SH共有ロック
LOCK_EX排他的ロック
LOCK_UNロック解除
LOCK_NBロック中にflock()でブロックさせない

共有ロックは、他のユーザーにファイルの読み取りは許可するけれど、書き込みは許可しない場合に使います。排他的ロックは読み込みも書き込みも許可しません。

ロックを行っている最中に他の人が同じファイルを開いてロックをかけようとすると、こちらのロックが解除されるまで他の人は待機した状態となり、こちらのロックが解除されると待機していた人のロックが行われることになります。そうではなく、自分がロックを行っている最中に他の人がロックをかけようとすると、待機させるのではなくすぐにロック失敗とさせる場合に「LOCK_NB」を使います。「LOCK_NB」は単独で指定するのではなく「LOCK_SH | LOCK_NB」のように他の値と同時に指定します。

実際の流れとしては下記のようになります。

$fp = fopen('filename', 'mode');

if (flock($fp, LOCK_EX)){
    // ファイルに対する操作を行う

    flock($fp, LOCK_UN);
}else{
    print('ファイルロックに失敗しました');
}

fclose($fp);

ロックの解除を忘れていても、該当のファイルに対するハンドルをクローズするとロックが解除されます。

サンプルプログラム

では実際に試して見ます。

functest41.php

<html>
<head><title>PHP TEST</title></head>
<body>

<?php

$fp = fopen('sample.txt', 'r');

if (flock($fp, LOCK_EX)){
    print('ファイルロックに成功しました<br>');

    flock($fp, LOCK_UN);
}else{
    print('ファイルロックに失敗しました<br>');
}

$flag = fclose($fp);

if ($flag){
    print('無事クローズしました');
}else{
    print('クローズに失敗しました');
}

?>
</body>
</html>

上記ファイルをWWWサーバに設置しブラウザ経由で見ると下記のように表示されます。

flockのテスト

( Written by Tatsuo Ikura )