#pragma twice

KAB-studio > プログラミング > #pragma twice > 276 Version 14.09 セマフォで排他処理

#pragma twice 276 Version 14.09 セマフォで排他処理

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

 Version 14.09
セマフォで排他処理

前回はセマフォを使ったプログラムを紹介しました
ミューテックスと違ってバトンはふたつ、ってことだったね
というわけで、今回は実際にそれを試してみます。ミューテックスの時、
つまり Version 14.06 ( No.273 ) の時と同じように、 
ProcessA ProcessB ProcessC の3つのプロジェクトを用意して
ミューテックスの時のをそのまま使ってもいい?
もちろん。同じようにボタンを5つずつ作って

Create()    // セマフォを作成します。
Open()      // セマフォを取得します。
Wait()      // セマフォを監視して待機状態に入ります。
Release()   // セマフォを手放します。
Close()     // セマフォを削除します。

を呼ぶようにしてください
この辺も同じね
さて、では実際に試してみます。前回のプログラムでは

// セマフォを作成します。
void Create()
{
    g_hSemaphore = CreateSemaphore( NULL, 2, 2, SEMAPHORE_NAME );
    TRACE( "%x\n", g_hSemaphore );
}

としました。つまり、バトンの数は2、最初の空いている数もその2、と
いうことになります
バトンは2本ね
今、 ProcessA ProcessB ProcessC の3つのプロセスを使うので、当然ひ
とつ余ります
余ると?
余ると、バトンが空くのを待つことになります。余らなかったふたつのプ
ロセスは、バトンをもらったらすぐに処理をします
ん〜?
というわけで実際に試してみましょう。まず

ProcessA::プロセス実行
ProcessB::プロセス実行
ProcessC::プロセス実行

と、まぁ普通に3つともデバッグ実行してください
はーい
次に

ProcessA::Create()
ProcessB::Open()
ProcessC::Open()

と、 ProcessA はセマフォを作成して、残りのふたつはそのセマフォを開
いてください
名前が同じだから、同じセマフォを開くんだね
そういうこと。これで準備はできました。それでは同期のテストを開始し
ます。まず、現在のバトンの状況はこうなっています

バトン1:空き
バトン2:空き

バトン2本とも空いてるわけね
次に

ProcessA::Wait()

と、 ProcessA はセマフォを監視してください
ほい。……あれ? 待たないよ? あっという間に待機終了。しちゃった
よ?
それがセマフォ、ってこと。前回説明したでしょ

○バトンの数が1以上:
 ・バトンをもらって動作開始
 ・バトンの数が1減る
○バトンの数がゼロ:
 ・バトンがないので、バトンが空くまで待ちます。
 ・バトンはゼロのまま

ああ! バトンは2本ある、そのうちの1本もらって動作開始、動作開始
ってことは待たないってことだから、 WaitForSingleObject() からすぐに
返ってきちゃうんだ!
そういうこと。だから、現在の状況は

バトン1:ProcessA 所有中
バトン2:空き
ProcessA::バトン1所有中(よって処理中)
ProcessB::何もしてません
ProcessC::何もしてません

という状況
バトン1が ProcessA に渡って、 ProcessA はそのバトン受け取ってなん
かしてるはず、ってわけね
次に

ProcessB::Wait()

と、 ProcessB もセマフォを監視してください
これもバトン取っちゃうからすぐに返ってくるんだよね。うん、返ってき

現在の状況はこうなります

バトン1:ProcessA 所有中
バトン2:ProcessB 所有中
ProcessA::バトン1所有中(よって処理中)
ProcessB::バトン2所有中(よって処理中)
ProcessC::何もしてません

この状態では、バトンの空きがありません
2本とも使われてるわけね
イメージとしては、トラック2つの競技場を、選手ふたりがバトンを持っ
て全力疾走してるイメージ
全然疾走してないけど
さて、この例で行くと ProcessC はもうひとりの走者ということになりま
す。ですが
バトンがないから走れない!
そういうこと

ProcessC::Wait()

として、 ProcessC もセマフォを監視してください
ほい。お、今度は返ってこない! ずっと待機開始。のままだ
現在の状態はこうです

バトン1:ProcessA 所有中
バトン2:ProcessB 所有中
ProcessA::バトン1所有中(よって処理中)
ProcessB::バトン2所有中(よって処理中)
ProcessC::バトンが空くのを待っています

バトンは2本しかありません。が、すでに ProcessA と ProcessB が持っ
ているため、 ProcessC はバトンが空くのを待っています
だから WaitForSingleObject() から返ってこないわけね
そこで、バトンをひとつ手放します

ProcessA::Release()

 ReleaseSemaphore() はセマフォのカウントを減らす、つまりバトンを返
す関数です
これを呼ぶと……あ、 ProcessC が待機終了。になった!
この瞬間を見てみましょう。まず、 ReleaseSemaphore() が呼ばれたこと
でバトンがひとつ空きます

バトン1:空き
バトン2:ProcessB 所有中
ProcessA::何もしてません(バトン1を手放したため)
ProcessB::バトン2所有中(よって処理中)
ProcessC::バトンが空くのを待っています

すると、一番最初に待機していたプロセスに、シグナルがオンになったこ
とが伝えられます

バトン1:空き→→→→→→→→→→→→→→→→→
バトン2:ProcessB 所有中                      ↓
ProcessA::何もしてません                       ↓
ProcessB::バトン2所有中(よって処理中)       ↓
ProcessC::バトンが空いた!←←←←←←←←←←←

そこで、 ProcessC はさっそくバトン1を取得します

バトン1:ProcessC 所有中
バトン2:ProcessB 所有中
ProcessA::何もしてません
ProcessB::バトン2所有中(よって処理中)
ProcessC::バトン1所有中(よって処理中)

バトンを受け取ったので監視は終了、処理を開始するわけです
なるほどねー。つまりさ、バトンをパスしたってことでしょ?
そういうこと。 ProcessC っていうランナーは ProcessA と同じコースで
待機していて、 ProcessA からバトンを受け取ったので全力疾走開始。 
ProcessA は代わりに走るのをやめたわけです
まさにリレーねー
実際のところ、ミューテックスもセマフォも〈バトンリレー〉をするため
の仕組みだから
そか、できて当然ってわけね
ただ、ミューテックスとセマフォって仕組みとか使い方が違うから
確かにこれは混乱するよね……セマフォのデフォルトのカウントとか
でもやりたいことは一緒。これをちゃんと理解できてればミューテックス
と同じように普通に使えると思うよ

/*
    Preview Next Story!
*/
次回はタイマーね。あれ? でもタイマーって前に使わなかった?
タイマーって全部で3つくらいあるから
そのうちのひとつ?
そゆこと
というわけで次回
< Version 14.10 タイマーを使おう! >
につづく!
ちなみに一番使わないタイマー
え”
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。