Perlサンプル15 ファイルアクセスの競合整理
投稿:2020-01-21
例えばファイルといった1つの資源をCGIのように非同期に呼ばれると競合して誤動作しますよね。 昔のホームページですとアクセスカウンタをファイルで管理していて、競合を整理できずにカウント値が吹っ飛ぶとかありました(老眼)。 そういう「同時にアクセスした際に一瞬でも先着したほうを優先、後着は先着の処理が全部終わるまで待たせる」処理を書いてみました。
このページを2個のタブでそれぞれ表示させてから、順にリンクをクリックしてみてください。 先着のほうが1秒ずつ「待機中」を表示して10秒待って終了します。 後着は「ロック開始」から進まずに先着が終了後に再開します。
サンプル4サンプル4の実行結果 処理開始 只今の日時は2020-01-21 20:53:10です。 ファイルオープン ロック開始 ロック完了 待機中(0) 待機中(1) 待機中(2) 待機中(3) 待機中(4) 待機中(5) 待機中(6) 待機中(7) 待機中(8) 待機中(9) アンロック開始 アンロック完了 ファイルクローズ 元のページに戻る
#/usr/bin/perl
use utf8;
use strict;
use warnings;
use DateTime;
use Fcntl qw(:flock);
binmode STDOUT, ":utf8 :crlf";
$| = 1;
print <<EOF;
Content-Type: text/html;charset=UTF-8
<html>
<head>
<title>サンプル4の実行結果</title>
</head>
<body>
<p>
サンプル4の実行結果<br />
</p>
<p>
EOF
print "処理開始<br />\n";
my $dt = DateTime->now(time_zone => "local");
print $dt->strftime("只今の日時は%F %Tです。<br />\n");
print "ファイルオープン<br />\n";
open my $single_fh, ">", "sample4.single";
print "ロック開始<br />\n";
if (flock $single_fh, LOCK_EX) {
print "ロック完了<br />\n";
for (my $i = 0; $i < 10; $i++) {
print "待機中($i)<br />\n";
sleep 1;
}
print "アンロック開始<br />\n";
flock $single_fh, LOCK_UN;
print "アンロック完了<br />\n";
}
close $single_fh;
print "ファイルクローズ<br />\n";
print <<EOF;
</p>
<p>
<a href="../sample/0f_perlsample_015.html">元のページに戻る</a><br />
</p>
</body>
</html>
EOF
flockで1つのファイルをロックして競合を整理しますので、こちらをご覧ください。
Perlの組み込み関数 flock の翻訳 - perldoc.jp