flock

ファイルをロックする

構文

解説

flockFILEHANDLE を通して該当のファイルをロック (排他制御) するために使われます。 実際には flock(2) を呼び出すか、もしくは、それをエミュレートします。 ロックに成功すれば真を返し、失敗すれば偽を返します。

OPERATION にはロックの種類を指定します。 詳細は後述しますが、排他的ロックなら 2 を、ロック解除なら 8 を指定します。 次のコードは、ファイルを開き、それを排他的ロックし、10 秒後にロックを解除します。

open my $fh, '<', './sample.txt';
flock $fh, 2 or die "Failed to lock a file: $!\n";    # 排他的ロック
sleep 10;
flock $fh, 8;                                         # ロック解除

もしすでに該当のファイルが別のプロセスによりロック中なら、上記コードの 2 行目 の flock は、 そのロックが解除されるまで待たされます。

OPERATION を数字で表すのはコードの可読性を低下させますので、 Fcntl モジュールを使ってシンボル名で表現すると良いでしょう。 次のコードは、前述のコードをシンボル名で書き換えたものです。

use Fcntl qw(:flock);
open my $fh, '<', './sample.txt';
flock $fh, LOCK_EX or die "Failed to lock a file: $!\n";    # 排他的ロック
sleep 10;
flock $fh, LOCK_UN;                                         # ロック解除

OPERATION に指定可能な値は下表の通りです。

シンボル名 ロックの種類
LOCK_SH 1 共有ロック
LOCK_EX 2 排他的ロック
LOCK_UN 8 ロック解除
LOCK_NB 4 ブロックなし

共有ロック (LOCK_SH) とは、同じ共有ロックであれば、お互いを排除しません。 しかし、排他ロックをしようとすると、最初の共有ロックが解除されるまで、排他ロックはブロックされ待たされることになります。 一方で、排他ロック (LOCK_EX) とは、ロックの種類に関わらず、すべてのロックをブロックします。

ブロックなし (LOCK_NB) は単独で使うのではなく、共有ロック (LOCK_SH) または 排他ロック (LOCK_EX) とともに使います。 OPERATION には LOCK_EX | LOCK_NB のように指定します。 1 つのプロセスがファイルを LOCK_EX | LOCK_NB でロック中に、 もう一つのプロセスが LOCK_EX | LOCK_NB で同じファイルをロックしようとすると、 ブロックされず即時にロック失敗となります。つまり、flock は待つことなく即座に偽を返すことになります。

次のコードは、ブロックなし (LOCK_NB) の例を示しています。 このコードによってファイルがロック中の間に、別のプロセスが同じコードを実行した場合、 即座に flock が失敗となり、エラーが出力されることになります。

use Fcntl qw(:flock);
open my $fh, '<', './sample.txt';

if ( flock $fh, LOCK_EX | LOCK_NB ) {
    print "Locked\n";
    sleep 10;
    flock $fh, LOCK_UN;
}
else {
    print "Failed to lock a file: $!\n";
}