PHPプログラミング

最終更新日:
公開日:

レシピ

ファイル / ディレクトリ

flock関数でファイルをロックする

flock関数でファイルロックを行う方法について解説します。

この記事のポイント

  • ファイルのロック&解除を行う
  • 共有ロックは同じ共有ロックのみ受け付ける
  • 排他ロックは他のロックを受け付けず、先に他のファイルロックがある場合はロックできない

目次

ファイルをロックしてファイルを安全に扱う

flock関数を使うと、特定のファイルに対しロックを行います。

コード例

flock( $file_handle, LOCK_SH);

第1パラメータはファイルポインターリソース(ファイルハンドラー)を指定し、第2パラメータは「LOCK_SH」などの定数を指定します。
使用できる定数は次の4種類です。

意味
LOCK_SHファイルを共有ロックします。ロック中は同じ共有ロックのみ許可し、排他ブロックは受け付けません。
LOCK_EXファイルを排他ロックします。ロック中は共有ロック、排他ロックいずれも受け付けません。
LOCK_UNファイルロックを解除します。共有ロック、排他ロックいずれもこの定数で解除できます。
LOCK_NB他のファイルロックがありロックできない場合、ロックをキャンセルします。他の定数と「| (パイプライン)」で組み合わせて使用します。

使用例

ファイルロックの基本的な流れは次のようになります。

コード例

<?php

// ファイルを開く
$file_handle = fopen('test.txt', 'r');

// ファイルロック(共有ロック)を実行する
if( flock( $file_handle, LOCK_SH | LOCK_NB) ) {

	while( $file_line = fgets($file_handle) ) {
		echo nl2br($file_line);
	}
	
	// ロックを解除
	flock( $file_handle, LOCK_UN);
}

// ファイルを閉じる
fclose( $file_handle);

if文の中でflock関数を実行しています。
定数「LOCK_NB」を指定しているため、もしファイルロックが行えなかった場合はif文の中は実行されません。
ファイルロックができた場合に限り、while文でファイル内容を出力します。

共有ロックの場合、同じ共有ロックであれば他のロックも受け付けます。
例えば、次のようにファイルロックを2箇所で行うことができます。

コード例

<?php

// 1つ目のファイルを開く
$file_handle = fopen('test.txt', 'r');

// ファイルロック(共有ロック)
if( flock( $file_handle, LOCK_SH | LOCK_NB) ) {

	while( $file_line = fgets($file_handle) ) {
		echo nl2br($file_line);
	}

	// 2つ目のファイル読み込み
	$file_handle2 = fopen('test.txt', 'r');

	// 2つ目の共有ロック
	if( flock( $file_handle2, LOCK_SH | LOCK_NB) ) {
		
		while( $file_line = fgets($file_handle2) ) {
			echo nl2br($file_line);
		}
	
		flock( $file_handle2, LOCK_UN);
	}

	// 2つ目のファイルを閉じる
	fclose( $file_handle2);
	
	flock( $file_handle, LOCK_UN);
}

// 1つ目のファイルを閉じる
fclose( $file_handle);

1つ目のファイルでロック中ですが、2つ目のファイルロックも受け付けて「test.txt」の内容が2度出力されます。
もしいずれかが排他ロックの場合、2回目のファイルロックは失敗します。

コード例

<?php

// 1つ目のファイルを開く
$file_handle = fopen('test.txt', 'r');

// ファイルロック(共有ロック)
if( flock( $file_handle, LOCK_SH | LOCK_NB) ) {

	while( $file_line = fgets($file_handle) ) {
		echo nl2br($file_line);
	}

	// 2つ目のファイル読み込み
	$file_handle2 = fopen('test.txt', 'r');

	// 2つ目の共有ロック
	if( flock( $file_handle2, LOCK_EX | LOCK_NB) ) {
		
		while( $file_line = fgets($file_handle2) ) {
			echo nl2br($file_line);
		}
	
		flock( $file_handle2, LOCK_UN);
	}

	// 2つ目のファイルを閉じる
	fclose( $file_handle2);
	
	flock( $file_handle, LOCK_UN);
}

// 1つ目のファイルを閉じる
fclose( $file_handle);

1つ目のファイルは共有ロック「LOCK_SH」ですが、2つ目のファイルは排他ロック「LOCK_EX」のため、2つ目のファイルについてはロックができず処理が実行されません。