#pragma twice

KAB-studio > プログラミング > #pragma twice > 271 Version 14.04 同期オブジェクト

#pragma twice 271 Version 14.04 同期オブジェクト

前のページへ 表紙・目次へ 次のページへ

 Version 14.04
同期オブジェクト

前回はファイルの排他処理について説明しました
他のアプリが書き込めないようにする方法だよねー
でも、あの方法にはデメリットもあります

■メリット
・お手軽
・他のアプリからファイルを守る

■デメリット
・同じアプリでもプロセスが違うとアクセスできない
・通知が面倒

このメリット・デメリットを考えると、最終的に一番いいのは

・ファイルはリードオンリーにしてひらく。
・ファイルにアクセスするのは1プロセスのみとする。
・ファイルにアクセスできるプロセス2つ以上実行しない。

という形になります
ファイルアクセスはひとつだけ、他は……他は?
そのプロセスにアクセスしてデータを取得したり、マルチスレッドを
使ったり
あの〈複数同時に処理できる〉ってヤツね
マルチスレッドについてはあとに取っておくとして、まずはプロセス単位
での処理について見ていきます
はーい
プロセス内や複数のプロセス間で同期を取る方法はいくつかあります。メ
モリを共有したり、ひとつのプロセスを使って管理させたりと……でも、
API には実は同期処理専用のシステムが用意されてるんです
専用のシステム?
そう、その名も【同期オブジェクト】
どうきおぶじぇくと、ってそのまんまね
 API の同期オブジェクトには5種類あります

ミューテックス ( Mutex )
セマフォ ( Semaphore )
タイマー ( Waitable timer )
イベント ( Event )
クリティカルセクション ( Critical Section )

うわー、なんか聞き慣れない英単語が結構ある……
さて、簡単にどういう機能を持つか説明するけど、そのまえにひとつ用語
を憶えてもらいます

用語は【シグナル】
しぐなる? 信号とかの?
そう、あのシグナル。まず、同期オブジェクトはシグナルを持っていま

信号機が内蔵されてるみたいな感じね
で、 API には【シグナルを見張る関数】があります
同期オブジェクトの中の信号を見張る、ってこと?
そういうこと。この関数は、シグナルがオフの間はずーっと見張り続けて
いて、オンになったら見張るのをやめます
見張るのをやめる?
具体的に言うと関数から返るってこと
……ってことは、その関数を呼ぶと、同期オブジェクトのシグナルがオン
にならない限り戻ってこない、と
ただ制限時間をつけることができるから、その制限時間内にオンにならな
くても自動的に返ってきます
オンになるか、時間になるか、ね
これが重要なのは、 Version 14.01 ( No.268 ) で

void Use_ファイル一覧取得関数()
{
    ファイル一覧取得関数( "C" );
    ファイル一覧取得関数( "D" );

    両方取得するまで待つ();
    ファイル一覧を出力する( C ドライブ );
    ファイル一覧を出力する( D ドライブ );
}

あ! 両方取得するまで待つ!!
そういうこと。この関数を使うことで〈終わるまで待つ〉ことができるん
です
便利……っていうか、こういうのがちゃんと用意されてるってことだね
そういうこと。さて、この待つ方はいいとして、今度は同期オブジェクト
の話。同期オブジェクトには今言ったようにシグナルが内蔵されているんだ
けど、それぞれ〈オンにする方法〉が異なるんです
それを使い分けなきゃいけない、と
そういうこと。というわけで、ひとつずつ見ていきます。

ミューテックス ( Mutex )

みゅーてっくす、ねぇ。なんか化学製品みたい
これは略語で、本当は【 MUTually EXclusive 】っていいます
みゅーちゃりぃえくすくるーしぶ?
日本語で言うと【相互排他】
あ、排他処理!
その排他。この同期オブジェクトは単純な排他処理をしたい場合に使いま
す。たとえば、プロセスAが〈テスト〉という名前のミューテックスを作る
とします
名前を付けられるんだ
普通はアプリのフルパスを名前にするんだけど今回はわかりやすく。で、
次にプロセスBから〈テスト〉って名前のミューテックスを作ろうとする
と、既に作られているのが返されます
プロセスが違っても同じものってこと?
そういうこと。ウィンドウズシステム内のものだからね。さて、この 
ミューテックスのシグナルは、初めは〈オフ〉になっています
さっきのシグナルね
そのため、プロセスBがこのミューテックスのシグナルを監視すると、当
面はそこで待機することになります
シグナルがオフだもんね。で、それをオンにするには?
プロセスAが〈テスト〉ミューテックスを手放せばオンになります
それだけ?
それだけ。つまりミューテックスは〈所有者が手放すとオンになる〉とい
うことです
……なんか拍子抜け……つまり、

【プロセスA】                    【プロセスB】
Mutex〈テスト〉 作成
(この状態でシグナルオフ)
                                  Mutex〈テスト〉を監視開始。
                                  シグナルオフなので待機中……。
Mutex〈テスト〉を解放
シグナル:オン→→→→→→→→→→待機終了。
                 処理再開。

って感じ?
そういうこと。こうすることで、実際の処理がたったひとつのプロセスで
だけ行われるようにすることができます
ほー
さらに、ミューテックス〈テスト〉をふたつのプロセスで監視していた場
合は、先に監視していたプロセスにだけ通知されて、後から監視したプロセスはその
まま待機を継続します

つまり

(プロセスAは上記と同じ)
  【プロセスB】                  【プロセスC】


  Mutex〈テスト〉を監視開始。     
  シグナルオフなので待機中……。  
                                  Mutex〈テスト〉を監視開始。
                                  シグナルオフなので待機中……。
→待機終了。                      (監視開始がプロセスBより遅い
 処理再開。                      ので、シグナルはオンになりません)
Mutex〈テスト〉を解放
シグナル:オン→→→→→→→→→→待機終了。
                 処理再開。

というふうになります
んー、つまりバトンはひとつ、ってこと?
そういうこと。この機能を使えば簡単に同期を取ることができます
なんかこれひとつあれば結構できそうだけど……他は?
では、次はセマフォ

セマフォ ( Semaphore )

意味は〈信号機〉
こっちの方が同期オブジェクトらしいね……
セマフォはほとんどミューテックスと同じ。違うのは、カウンターが付い
ているところ
カウンター? 数数えるの?
そう。さっきの火美ちゃんの例で言うと、〈バトンがひとつ〉なのが
ミューテックス、〈バトンが複数個ある〉のがセマフォ
バトンが複数個? さっきの例だと……たとえばバトンふたつなら、
プロセスAと一緒にプロセスBも動けて、でもプロセスCは待つみたい
な?
そういうこと。セマフォは、同時の処理を2つ以上するけど、でも有限個
にしたい場合に使います。次はタイマー

タイマー ( Waitable timer )

これは一定時間毎にシグナルがオンになる、それだけの機能
これはちょっと他と違うね
というかミューテックスとセマフォが似てるってだけかも
ってことは、他の同期オブジェクトもだいぶ違う?
だいぶってほどではないかな……

イベント ( Event )

イベントは、シグナルのオンとオフを切り替えることができる同期オブ
ジェクトです
??? それってミューテックスとかと同じじゃん
それは違うよ。ミューテックスは、プロセスAが解放した時、シグナルが
オンになったのを伝えられたのはプロセスBだけ。プロセスCからは
シグナルがオフって見えていたんです
そういえば待ち続けているんだもんね
さらに、そのあと他のプロセスがミューテックスを監視したときには、
プロセスBが持っている間はシグナルがオフになっています
そか、常に誰かが持ってるから、シグナルがオンになるのは一瞬……
それに対して、イベントはシグナルをオンにするとオンになりっぱなし
おお
そして、オンになったことを全員知ることができるから
全員待機から抜けるね
機能的にはこっちの方が信号っぽいかもね。では最後

クリティカルセクション ( Critical Section )

クリティカルセクションは他の同期オブジェクトとは全く違っていて、
〈プログラム〉に排他処理を行います
プログラム……に?
たとえばある関数を同時に複数のプロセスが実行できないようにする、と
か。ファイルや変数じゃなく、プログラムのコードに排他処理をするってこ

んー???
いまいちメリットがつかめないのかもね……まぁその辺はあとで詳しく

/*
    Preview Next Story!
*/
次回は実際にミューテックスを作ってみます
簡単? 難しい?
作るだけなら簡単
使う時は?
使うだけでも簡単
じゃあいつ難しいの!?
というわけで次回
< Version 14.05 ミューテックスを使おう! >
につづく!
難しくないんです
なぁんだー
嘘ですごめん
!!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。