Linux
Perlでの排他制御(lock)
排他制御とは
ファイルやデータベースに書き込み処理を行なう際に、データの整合性を保つために、データの読み書きを一時的に制限すること。
例えば、売上の累計金額を保管するファイルがあるとする。
「売上の累計金額の読み込み」→
「売上の累計金額の計算」→
「売上の累計金額の書き込み」
を一連の操作で行うことになるが、ほぼ同時に行った場合、
「Aが売上の累計金額の読み込み」→
「Bが売上の累計金額の読み込み」→
「Aが売上の累計金額の計算」→
「Bが売上の累計金額の計算」→
「Aが売上の累計金額の書き込み」→
「Bが売上の累計金額の書き込み」
となる。
そのため、「Aが売上の累計金額の書き込み」した結果をBが読み込みを行っていないため、Aの売上は、計算されていないことになる。
このような問題が起こらないようにすることが排他制御である。
自分以外の他のものを排除する(排他制御)は、ファイル(データ)をロック(鍵を)して行う。
また、今回説明しないが、2ファイル(データ)以上の排他制御を行う場合最も問題なるのは、「デッドロック」である。
では、Prelで
「売上の累計金額の読み込み」→
「売上の累計金額の計算」→
「売上の累計金額の書き込み」
を、行うスクリプトを書いてみよう。
open IN, '<','累計金額' or die "オープン失敗 $!";
$sum = <IN>;
close IN;
$sum += 100;
open OUT, '>','累計金額' or die "オープン失敗 $!";
print OUT $sum;
close OUT;
|
となる。(サンプルのため、売上金は、100固定にしている)
flockを使用した場合を考える。
flockは、ファイルをオープンしている必要がある。そのため
open IN, '<','累計金額' or die "オープン失敗 $!";
flockを入れる
$sum = <IN>;
close IN;
$sum += 100;
open OUT, '>','累計金額' or die "オープン失敗 $!";
flockを入れる
print OUT $sum;
close OUT;
|
となると思うのだが、ほぼ同時に行った場合の、問題点はクリアできていない。
open INOUT, '+<','累計金額' or die "オープン失敗 $!";
flockを入れる
$sum = <INOUT>;
$sum += 100;
truncate INOUT, 0; # ファイルサイズを0バイトにする
seek INOUT, 0, 0; # ファイルポインタを先頭に移動
print INOUT $sum;
close INOUT;
|
と、読み書きモードでオープンして、ロックし、一連の操作が終わるまで、クローズしない。
また、注意点としては、flockを行っても、openは、行える。ロック解除を待つのは、flockである。