Version 14.02
プロセスと同期
「マルチスレッドの話の前に、わかりやすい【プロセス】とその同期の説明
からします」
『プロセスって Version 8.04 ( No.146 ) でやったのだよね』
「そう。実行ファイル、つまり exe をダブルクリックすると作られるもの
です。プロセスには次のような機能があります」
・仮想メモリを管理する。
・WinMain() を呼び出す。
「まず、プロセスは仮想メモリを管理します。というか、仮想メモリは
プロセス毎に割り当てられる、っていう方が正しいかな」
『だから、プロセスが他のプロセスの変数にアクセスできないんだよね』
「そういうこと。あるプロセスで実行しているプログラムの変数のアドレス
が 0x00001234 のだとしても、他のプロセスで実行している同じプログラム
では 0x00001234 は別の変数が使っている、っていうことだから」
『アドレスがまったく違っちゃうわけね』
「もうひとつ、プロセスは WinMain() 関数を呼び出します」
『 Version 8.01 ( No.143 ) でやった、一番最初に呼ばれる関数ね』
「プロセスの機能はこのふたつ。このことを踏まえつつ、同期というものに
ついて見ていきます」
『どうき、シンクロナイゼーションってヤツね』
「まず、メモ帳を実行してください」
『……メモ帳って、アクセサリの?』
「そう。スタートメニューから【プログラム】>【アクセサリ】のメモ帳。
この中に」
いち。
「と書いて、適当な場所に test.txt という名前で保存してください」
『ほい保存した』
「そうしたら、とりあえずメモ帳を終了してください」
『ほい閉じた』
「さて、ここからです。まず、もう一度メモ帳を実行して、このファイルを
読み込んでください」
『実行して、【ファイル】を【開く】で、と。うん、開いたよ』
「そうしたら、もうひとつメモ帳を実行して、同じようにこのファイルを読
み込んでください」
『同じファイルをふたつのメモ帳で開くってこと?』
「そういうこと」
『ん、開いたよ。メモ帳ふたつ、両方とも〈いち。〉って書かれてる』
「さて。このふたつのメモ帳ひとつひとつが【プロセス】です。つまり、今
メモ帳のプロセスがふたつあるということになります」
『実行するたびに増える、ね』
「このふたつを、メモ帳A、メモ帳Bとします」
『どっちがAでどっちがB?』
「実行した順番とかは関係ないから、どっちでもいいよ」
『はーい』
「さて、プロセスごとの仮想メモリは別々なので、たとえばメモ帳Aからメ
モ帳Bの内容を変える、ということは基本的にできません」
『メモ帳Aを操作してたらいつの間にかメモ帳Bも変わってた、ってことは
ないわけね』
「そのため、プロセスの単位では、自分のメモリが勝手に書き換わるという
こと心配する必要はありません。ですが、メモリの外、たとえばファイルで
は心配する必要があります」
『 test.txt のこと?』
「そういうこと。ここでメモ帳Aを見てみます。これからする仕事が〈書か
れている数を1増やして保存する〉というものの場合、メモ帳Aでの作業
は?」
『1増やすんでしょ? 今〈いち。〉って書かれてるんなら〈に。〉?』
「そういうこと。じゃあ火美ちゃん、実際にやってみて」
『ほい。〈いち。〉を消して〈に。〉にして保存、と』
「さて、次はメモ帳Bに同じことをしてみて」
『ほい。〈いち。〉って書かれているから〈に。〉で保存、ね』
「ところが、本当はこの時点で test.txt には〈に。〉って書かれているか
ら」
『あ……本当は〈に。〉から〈さん。〉にしなきゃいけない……』
「そういうこと。でもメモ帳Bはそのことを知らないから、今メモ帳Bが
知っている〈いち。〉を1増やすしかないんです」
『メモ帳Aでやったのが無駄になっちゃうね』
「もしこれが、インターネットのアクセスカウンターだとしたら」
『げ、お客の数減っちゃう!』
「以上を流れにするとこうなります」
test.txt :〈いち。〉
メモ帳Aが開く:〈いち。〉
メモ帳Bが開く:〈いち。〉
メモ帳Aが書く:〈に。〉
test.txt :〈に。〉
メモ帳Bが書く:〈に。〉
test.txt :〈に。〉
『うーん、ホントに無駄ね……』
「この問題の解決方法は〈メモ帳Bは、処理をする前に最新の情報を取得す
る〉ということです」
『メモ帳Bが最新情報を取得すれば、メモ帳Bは〈に。〉ってことがわかる
からそれを増やして〈さん。〉、ってわけね』
「そのためにはいくつか方法があります」
1.メモ帳Aが開いている間はメモ帳Bは開けないようにする
2.メモ帳Aが開いている間はメモ帳Bは書き込めないようにする
3.メモ帳Aが閉じたらそのことをメモ帳Bに報せるようにする
「この辺が主なところかな」
『確かにこれなら、メモ帳Bが間違って書き込むことないね』
「では、この例を実際に試してみましょう。まず Excel を開いて」
『えくせる、ってマイクロソフトのエクセル?』
「そう、その Excel 。これを開いて、最初のセルに〈1〉を入力してくださ
い」
『ほい』
「次に、これを〈他のマシンの共有フォルダ〉に保存してください」
『他のマシン……?』
「そう。今回のテストはネットワーク経由でないとダメだから」
『そうなんだ。ほい』
「で、その〈他のマシン〉からこのファイルを Excel で開きます。これ
が、さっきの例での【メモ帳A】に当たります」
『最初に開いておく方は、他のマシンから、ってわけね』
「次にこれをこのマシンから開きます」
『これが【メモ帳B】に当たるわけね。あ、なんか出た!』
[使用中のファイル]
test.xls は編集のためロックされています。
「このダイアログそのものが、同期処理のひとつ。普通に開くことができた
ら」
『さっきのメモ帳みたいにまずいことになるもんね』
「で、右側に3つのボタンがあるでしょ」
読み取り専用
通知
キャンセル
「この3つが、さっきの」
2. Excel Aが開いている間は Excel Bは書き込めないようにする
3. Excel Aが閉じたらそのことを Excel Bに報せるようにする
1. Excel Aが開いている間は Excel Bは開けないようにする
「に当たります」
『メモ帳が Excel になってる。あ、あと、順番変わってるのはボタンと合
わせてるから?』
「そう。ひとつひとつ見ていこうか」
読み取り専用
2. Excel Aが開いている間は Excel Bは書き込めないようにする
「このボタンを押すと、開いたファイルは保存できなくなります」
『 Excel Aと Excel Bの両方で修正しても、 Excel Bの方は保存できな
いから大丈夫、ってわけね。でも Excel Bの方は無駄骨』
「確かに。だからプログラムではこの方法はあまり使わないかな。それこ
そ、ユーザーにこんな感じに選択してもらうときの選択肢のひとつかも」
『不便だもんね』
「では次」
通知
3. Excel Aが閉じたらそのことを Excel Bに報せるようにする
「通常、 Excel Bは〈報せが来るまで何もしない〉ようにします」
『何もしない、ただ待つだけ?』
「そう。で、報せが来たらその時点で読み込みます」
『そか、そうすれば Excel Aが修正した内容がわかるわけね』
「ただし、こういう【待機系】の処理は、タイムアウトが必須になります」
『だよね、ずっと掴まれてたらずっと固まったままだもん』
「それと、この〈報せる〉っていうのを実装するのもちょっと面倒です」
『んー、メッセージ送ったりすればいいんじゃないの?』
「そのためには、 Excel Bは〈ファイルを開いているのは Excel A〉とい
うことを調べて、 Excel Aに〈ファイルを閉じたら自分にメッセージ送っ
て〉と伝えて、そして Excel Aはその通り実行できなきゃいけない」
『うわ、確かに面倒そう……』
「実際には、同じプロセス同士が情報を共有する形で、誰がどのファイルを
開いているかを知っておく、っていう形になるかな」
『……ねぇ、それってメモリ上? ならこの前のマルチスレッドってのと同
じじゃん』
「まぁ、結局そうなるんだけどね……さて、3つめの方法」
キャンセル
1. Excel Aが開いている間は Excel Bは開けないようにする
「実際には、 Excel Bは少し待ってからもう一度開こうとしてみて、開け
たら開く、開けなかったらまた待つ、っていうのを繰り返すことになりま
す」
『ファイルにロック掛けちゃうわけね。あ、そういえば時々そういうのって
あるよね、なんかファイルを開くことも削除することもできなくなる時っ
て』
「そう、ウィンドウズのファイルシステムに〈ファイルにロックを掛けて、
他のアプリが操作できないようにする〉方法があります」
『ちゃんとそういうのが用意されてるんだ』
「これを【排他処理】っていいます」
『はいたしょり?』
「そう、〈他を排斥する〉、他からのアクセスを拒否する仕組み。これはプ
ログラミング一般の用語だから憶えておいて」
『はーい』
「さて、まとめると、ひとつの共有リソース――たとえばファイル等――に
複数のプロセスが同時に読み書きする場合には、そのタイミングを取る、つ
まり同期を取らなければなりません」
『そうしないと間違った情報を元に処理して書き込んじゃうからね』
「その処理の具体的な方法が【読み取り専用】、【通知】、【キャンセル】
のみっつ。というわけでこれらの実装方法について見ていきます」
/*
Preview Next Story!
*/
『はー、なんか本格的なアプリって感じ』
「その意識は大事かも?」
『どゆこと?』
「ちゃんと同期を取らないとファイルを壊したりすることもあるから」
『げ、そっか、本格的にしないとまずいってことね』
「というわけで次回」
< Version 14.03 ファイルの排他処理 >
『につづく!』
「というわけで次回は Excel っぽくしてみます」
『それっていいことなの?』
「ま、排他処理に関しては」