EnterCriticalSection()でスレッドをブロックしたとします。
この時、LeaveCriticalSection()で開放されたらブロックされているスレッドが実行
されますが、この時、実行される順序はブロックされた順序と考えていいのでしょうか?
例えば以下のコードですが、
CRITICAL_SECTION cs;
int main()
{
InitializeCriticalSection(&cs);
HANDLE hThread[10];
for(int i=0; i<10; ++i){
EnterCriticalSection(&cs);
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, TheadFunc, (void *)i, 0, &id);
LeaveCriticalSection(&cs);
}
WaitForMulipleObjects(10, hThread, TRUE, INFINITE);
DeleteCriticalSection(&cs);
return 0;
}
unsigned __stdcall ThreadFunc(void *p)
{
std::cout << (int)p << std::endl;
Sleep(1000);
_endthreadex(0);
return 0;
}
10個のスレッドを作成してますが、各スレッドはインデックスを出力して1秒待ちます。
この場合、私の環境だと0から9まで順に出力されますが、これは保証されているので
しょうか?
あと、いくつのスレッドがブロックされているかを確認するにはどうしたらよいので
しょうか?(CRITICAL_SECTIONにLock_Countってメンバーがあるけどこれ?)
というのもDeleteCriticalSection()するのに確実にブロックされているスレッドがない
ことを確認したいのですが方法が分からないです。(上の例では問題ないですが)
もし順序が保証されているのならDeleteCriticalSection()の直前EnterCriticalSection
()とLeaveCriticalSection()を実行すればOKなのでしょうが・・・
環境はVC++6SP6 WinXP MFC未使用です。
よろしくお願いします。
えっと、何をブロックしているのでしょうか、このコード。
CRITICAL_SECTION を1箇所だけで使っているのは無意味。
意味がわかりません。
ごめんなさい、例が悪かったです。
聞きたい事はクリティカルセクションの取得を待っているスレッドの数を知りたいので
す。
DeleteCriticalSection()する前に待機状態のスレッドがないことをチェックする必要が
あるからです。(MSDNだと待機中のスレッドがある状態で削除すると未定義とあるので)
あと、名前はミス入力でした・・・
ごく普通にマルチスレッドプログラムを組んだとすると、通常
InitializeCriticalSection はワーカスレッドが生成される前に実行する
DeleteCriticalSection はすべてのワーカスレッドが終了した後に実行する
ような構造になると思います。
となると Delete のタイミングでは Enter 待ちスレッドなど存在しない。
つまり何も考える必要は無い、ということだと思うのですがいかがでしょうか。
ご自分のサンプルでも
> WaitForMulipleObjects(10, hThread, TRUE, INFINITE);
と、すべてのスレッドが終了するのを待ってますよね。
多分、待ちキューの順番が保証されるかどうか?
といった質問だと思います。
これに関しては保証されません。
何故ならば、関数コールの順番自体を厳密に規定できないからです。
この場合EnterCriticalSection()を呼んだ瞬間からスレッドが眠りにつく迄の処理中
に別のスレッドに切り替わる場合があります。
・・・解り難いと思う。追加説明が必要ならば言ってください。
同様の理由で他の同期オブジェクト(Mutex,Semaphore)等の順番も保証されません。
では、例えば100スレッドがCriticalSectionを使って順番待ちをしている場合、
運の悪いスレッドは永遠に眠っている可能性があるのか?
というと、それはありません。
. . . .
ほとんど順番通りに起こされるハズです。
(実装的に順番通りに処理されるということ)
--------------------------------------------------------
大変なのは他人(客とか上司)を説得する場合ですが、、
厳密に順番を保証したモジュールは自分で作るしかありません。
--------------------------------------------------------
私の前に作ったモノ(I/Fの一部のみ:templateね)
--------------------------------------------------------
// 順序登録用(排他して呼ぶor厳密なモノに目をつぶれ。内部にも排他があるから)
int RegistOrder (KEY key,int priority = NOMAL);
// 順序制御区間-開始
int SectionStart (KEY key);
// 順序制御区間-終了
int SectionEnd (KEY key);
お二人とも、ありがとうございました。
いろいろと本や資料を見た結果、tetrapodさんのおっしゃる通り、
>Delete のタイミングでは Enter 待ちスレッドなど存在しない
ということに納得いたしました。
あと、実行される順序に関しては、それに依存するようにしてはならない、と解釈しまし
た。
マルチスレッドって奥が深いですね・・・
あ、チェック忘れてましたね・・・