Perlでのファイルロックについて
Perlでのファイルロックでは、普通、flock関数を使用します。
flock関数の第1引数にはファイルハンドルを指定し、第2引数には以下のいずれかの値を指定します。
尚、 LOCK_SHやLOCK_EX等を使用する場合は、『use Fcntl ':flock';』宣言が必要です。
- 1(LOCK_SH):共有ロック(ブロキングモード)
- 2(LOCK_EX):排他ロック(ブロキングモード)
- 5(LOCK_SH | LOCK_NB):共有ロック(ノンブロキングモード)
- 6(LOCK_EX | LOCK_NB):排他ロック(ノンブロキングモード)
- 8(LOCK_UN):ロック解除(closeでもロック解除される)
1は、本処理がファイルに対して他のプロセスの書込をロックし、本処理終了まで他のプロセスを待たせます。
2は、本処理がファイルに対して他のプロセスの書込読込をロックし、本処理終了まで他のプロセスを待たせます。
5は、本処理がファイルに対して他のプロセスの書込をロックし、他のプロセスは即時復帰(リターン値0)する。
6は、本処理がファイルに対して他のプロセスの書込読込をロックし、他のプロセスは即時復帰(リターン値0)する。
尚、本ロック処理は、同ファイルに対してflock関数を使っているプロセス同士で有効で、flock関数を使っていないプロセスでは無効です。このようなロックをアドバイザリーロックと呼ぶらしい…。
◆ 2のサンプル
use strict; use warnings; use Fcntl ':flock'; my $counter_file = 'counter.dat'; open my $fh, '+<', $counter_file or die "$!:($counter_file)"; flock $fh, LOCK_EX; # 排他ロックをかける print "---ロック中---\n";# デバック文 my $counter = <$fh>; # カウント値を読み込む $counter++; # カウントアップ seek $fh, 0, 0; # 書き込み位置をファイルの先頭に移動 print $fh $counter; # カウント値を書き込む sleep 5; # デバックで5秒待つ close $fh; # 排他ロックの解除する
◆ 5のサンプル
use strict; use warnings; use Fcntl ':flock'; my $retry = 3; # リトライ回数(3回) my $wait = 1; # リトライ時間(1分) my $counter_file = 'counter.dat'; open my $fh, '+<', $counter_file or die "$!:($counter_file)"; my $locked = 0; # 1でロックオン for (my $i = 0; $i < $retry; $i++) { if (flock $fh, LOCK_EX|LOCK_NB) { print "---ロック中---\n"; $locked = 1; last; } sleep $wait; } if ($locked != 1) { die '他のプロセスがロック中で処理できず!'; } my $counter = <$fh>; $counter++; seek $fh, 0, 0; print $fh $counter; sleep 4; # テストSleep close $fh;