ファイルロックのアルゴリズム

トップ > プログラミング研究 > 排他のアルゴリズム
一つ前にもどる 目次にもどる 次のページへ

排他処理のためのプログラム

共有するデータをMySQLといったようなDBMSで操作するときは、これらソフトが排他制御を行ってくれるので、割と簡単に排他の処理ができるらしいのですが、プロバイダーや無料のレンタルスペースだと、データベースソフトは使えないので、通常のテキストファイルをデータファイルとして、自分で排他制御する必要があります。(DBMSとの連携はまだ勉強中です・・)

ファイルロックのアルゴリズム

理屈は簡単です。自分が書き込みをしようと思ってファイルを開くときには、他の誰にもファイルを開かせない、それだけのことです。流れを書くと。

1.ファイルをロックして排他制御する。(これで、誰もファイルを開くことができない)
2.ファイルを開いてデータを参照
3.必要な処理を行う
4.ファイルに処理後のデータを保存
5.ファイルのロックを解除する。(誰でもアクセス可能な状態にする。)

以上です。

これは、書き込みを行う場合だけに発生する問題ですので、読み込みしかしないデータには排他の処理は無意味です。

そこで、サンプルとして使ってきたカウンターのプログラム(Perl)ではどのような手法で排他を行うかを考えてみたいと思います。

Perlには「flock」というファイルの排他制御を行う関数があります。ただ、これはサーバーのOSに依存するので、使えない場合があります。と書かれていることが多いのですが、自分の経験上、使えないというサーバーを使ったことがありません。WindowsNT系でも使えたので、おそらく大丈夫だと思います。(Windows9X系は使えません。!)

いろんなCGI用Perlスクリプトを配布しているサイトでは、Symlinkなどを利用してファイルの排他(ロック)を行っているようですが、Symlinkなどは、もともとファイルの排他をするためのものではなく、アルゴリズム的にも不完全だという指摘も聞きます。個人的には、不完全な排他なら、しないほうがいいのでは・・・とも思ってます。

flockを使ったファイルロックの方法

flockを利用してファイルに排他をかけることを考えると、以下のようなプログラムになりそうです。前回行ったカウンターのプログラムに排他をかける例で示してみます。

01: #!/usr/local/bin/perl
02:
03: # ロック用ファイルを作成
04: open(LOCK, ">lock.temp");
05: flock(LOCK,2); # ロック用ファイルをロックする
06:
07: # count.datというファイルから現在のカウント数を読み込む
08: open (IN, "count.dat");
09: $count=<IN>;
10: close(IN);
11:
12: # 現在のカウント数$countに1を追加
13: $count=$count+1;
14:
15: # 1増加したカウントを別の一次ファイルに保存
16: open (OUT, ">count.temp");
17: print OUT $count;
18: close(OUT);
19:
20: # 別の一次ファイルから本来のファイルに名前を変更
21: rename("count.temp","count.dat");
22:
23: # 最初に作ったロック用ファイルを削除
24: unlink("lock.temp");
25:
26: # ロックしたファイルを解除
27: flock(LOCK,8);
28: close(LOCK);
30:
31: # ここからHTMLでの表示
32: print "Content-Type: text/html\n\n";
33: print "<html><head><title>test</title></head>";
34: print "<body>";
35: print "あなたは $count 番目の訪問者です。";
36: print "</body></html>";
37:
38: __END__

*左端の番号は便宜的に付けた行番号です。

どうでしょうか?これで排他がかかりました。

プログラムの解説

それでは、一部簡単にですが、解説したいと思います。4~5行目で、以前はなかったロックのための処理を行います。ここで、ちょっと「おや?」と思うのは、今カウンターとして変更したいファイルは「count.dat」なのに、どうしてわざわざ別のファイル「lock.temp」を作って、それをロックするのか、ということです。

03: # ロック用ファイルを作成
04: open(LOCK, ">lock.temp");
05: flock(LOCK,2); # ロック用ファイルをロックする

上記のように別のファイルを利用するのは、変更をしたいファイルを直接ロックすることも可能なのですが、こうすると、ファイルを開いてロックをするまでの間に若干の時間的隙間ができてしまうので、その隙間の間にファイルを開くことが出来てしまうからです。

実際、自分のローカルマシンで短時間に直接ファイルをロックする方法で1000回書き込みを行うプログラムを書いて、2つ同時に実行させてみました。その結果、本来なら1000回のアクセスが2つ同時に実行されているので、カウンターは2000になるべきなのですが、全く違う数字になっていました。

その後、上記のように別にロックファイルを作ってそちらをロックしてから、ファイルの書き込みを行う処理に変更して同じ実験をしたのですが、こちらは、2つのプログラムの処理終了後はカウンターはちゃんと2000となっていました。

(この実験については、別の機会にここで公開します。ファイルロックは奥が深いことを思い知らされました・・・)

ということで、実験のように数秒間で1000以上のアクセスがあることなどは、個人のページではまずないと思うのですが、別にロックファイルを作った方が正しく処理ができるということが理解できます。

それ以降は、前回書いたカウンタープログラムと同じ手順ですが、ここで、更に一点違う場所があります。普通なら、1増加させたデータを直接カウンター用のデータファイル「count.dat」に書き込むべきなのですが、これをあえて別の仮ファイル「count.temp」に書き出しています。(16行をご覧ください。)

15: # 1増加したカウントを別の一次ファイルに保存
16: open (OUT, ">count.temp");
17: print OUT $count;
18: close(OUT);
19:
20: # 別の一次ファイルから本来のファイルに名前を変更
21: rename("count.temp","count.dat");

別のファイルに書き出した後に、21行目で名前を変更させて、元のファイルにしています。こうする理由ですが、ファイルを書き込んでいる途中でシステムが強制終了等になると、ファイルが壊れてしまうため、それを防ぐ目的です。(この部分のアイディアは、ここのレンタルサーバーの技術情報からお借りしました。m(__)m)

最後に、ロックファイル用に作成した仮ファイルを削除して、ロックを解除して処理終了です。

23: # 最初に作ったロック用ファイルを削除
24: unlink("lock.temp");
25:
26: # ロックしたファイルを解除
27: flock(LOCK,8);
28: close(LOCK);

ただ、17行目のロックの解除は「 close() 」がある場合は不要です。念のために書いています。

本当にロック(排他処理)は必要か?

最後に、ファイルのロックについていろいろと書きましたが、本当に排他の処理が必要か?という問いに関しては、少々疑問もあります。個人で作っているページのレベルなら排他処理をしなくても十分に耐えられるのかな・・・と思ってます。逆に、排他処理を行っていたにもかかわらず壊れてしまった、という経験もあります。

自分の経験を少しだけかくと・・・

アンケート集計のプログラムを書いたことがあります。20人程度が5分ほどの間にWeb上でアンケートに答えて、その集計を行うというものです。これを90日程度毎日繰り返したことがありましたが、排他処理なしで全く問題ありませんでした。たまたまかもしれませんが、これくらいの頻度で壊れることのないレベルです。日に50~100人程度のアクセスがある個人ページの掲示板くらいなら、排他処理はしなくてもOKなのかなぁ・・・とも思いますね。

正直、排他をかけた場合とかけない場合で、プログラム的にどの程度の負荷になるかはよくわかってませんが、下手な排他処理をかけるくらいなら、かけない方が壊れにくいのかなぁ、、、とも思いますね。ということで、前回「欠陥があります!」と書いておきながら矛盾しますが、ロックは時と場合に応じて・・・ということでしょうか?

商用サイトや、信頼性をかなり追求されるようなプログラムには必要でしょうが・・・というか、そういうサイトを作る場合は、そもそもDBMSなどのプログラムと連携させるべきでしょう。

ファイルロックは奥が深すぎて、最初に勉強・・・とおもって手がけるには大きすぎる課題でした。実験なども色々してみましたが、まとまりきっていないので、もう少しまとめてから公開したいと思います。m(__)m

一つ前にもどる 目次にもどる 次のページへ
(作成2003/09/19 by あいまい)

トップ > プログラミング研究 > 排他のアルゴリズム

日時: 2008年01月25日 11:19
newsingに投稿BuzzurlにブックマークBuzzurlにブックマークlivedoorクリップに投稿 Choixにブックマーク イザ!ブックマーク このエントリーを含むはてなブックマーク
トップに戻る
このエントリーの所属カテゴリ: プログラミング研究
このエントリーのタイトル:ファイルロックのアルゴリズム



copyright © 2000-2008 all rights reserved
あいまいモード・コム - rss2.0 atom
newsingに投稿BuzzurlにブックマークBuzzurlにブックマークlivedoorクリップに投稿 Choixにブックマーク イザ!ブックマーク このエントリーを含むはてなブックマーク