ファイルをロックする
flock
は FILEHANDLE を通して該当のファイルをロック (排他制御) するために使われます。
実際には 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";
}