ミューテックすについて

解決


ken  2013-03-11 15:30:14  No: 73641  IP: 192.*.*.*

初めまして、何度か見かける掲示板で解決してる物が多いようなので利用させていただきます。
現在 visual studio 2008 にてmfcを使ってダイアログベースのアプリを作成しています。
そこでスレッドを作成していてあるデータに対して排他制御があるので自分でフラグを作って同時にアクセスできない様にしていました。
中身はこんな感じです。

bool Flag = true;

void Lock(void)
{
     while(!Flag);

     Flag = false;
}

void UnLock(void)
{
     Flag = true;
}

これを使って競合が起きないようにしていたのですが、デバッグでは問題なく動作していたところ、Releaseで起動すると最適化のせいなのかフリーズしてしました。

自作のロック、アンロック部分をミューテックすに変えて
WaitForSingleObjectとReleaseMutexを使うように変更したら問題なく動くようになりました。

なぜ自作のものだと動かなくなっていまうのでしょうか?

長文失礼しました、よろしくお願いします。

編集 削除
YuO  2013-03-11 16:08:35  No: 73642  IP: 192.*.*.*

例えば,
> void Lock(void)
> {
>      while(!Flag);
>
>      Flag = false;
> }
を,
void Lock(void)
{
    if (Flag)
    {
        Flag = false;
        return;
    }
    while(true)
        ;
}
とした方が無駄がないと考えて,上記のようなコードを出力したのかもしれません。
# 実際にはアセンブリを出力させて読み取るくらいしか方法はありませんが。

まず,複数のスレッドから読み書きする変数は,volatileで修飾しておく必要があります。
これをしない場合,コンパイラは外部からの変更がないものとして最適化を行う可能性があります。

その上で,各種同期オブジェクトを使った方が効率がよくなります。
whileによるbusy-loopと異なり,各種同期オブジェクトによる待機は,利用できない間はCPU時間を使いません。

編集 削除
ken  2013-03-11 16:32:11  No: 73643  IP: 192.*.*.*

回答ありがとうございます。volatileで調べたところこんな便利な修飾があったんですね。  勉強になりました。

>>whileによるbusy-loopと異なり,各種同期オブジェクトによる待機は,利用できない間はCPU時間を使いません。
WaitForSingleObjectでブロッキングしていたので結局内部でもwhileによるbusy-loopと同じかと思っていたのですが、そうではないのですね。

まだまだ勉強不足です。
YuOさんありがとうございました。

編集 削除