- ベストアンサー
Mutexの次の使い方で
typedef struct{ HWND hwnd;BOOL th_end;HANDLE hmutex; } DATA, *PDATA; /////////////////////////////////////// static HANDLE hThread1,hThread2; DWORD threadID1,threadID2; static DATA data; static HANDLE hMutex; switch (msg) { case WM_CREATE: //hMutex= //CreateMutex(NULL,FALSE,NULL); data.hwnd = hWnd; data.th_end = FALSE; data.hmutex = hMutex; hThread1=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Thread1, (LPVOID)&data, 0,(LPDWORD)&threadID1); hThread2=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Thread2, (LPVOID)&data, 0,(LPDWORD)&threadID2); /*x*/hMutex= /*x*/CreateMutex(NULL,FALSE,NULL); break; とするのは正しくて/*x*/の行を削除して//をとり hMutexの位置を前に持ってくるのは間違っているのでしょうか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> エラーもでず動作の違いも峻別できませんでした Thread内のWaitForSingleObject()で失敗している と思われますが、このサンプルでは戻り値のチェック を行なっていません。スレッド間でリソースの競合が 発生していると思われます。
その他の回答 (4)
- nabezo-
- ベストアンサー率50% (2/4)
何回か質問を読み返しましたが、やっぱり私も何を目的とした質問か理解に苦しみます。。。 一応、回答しますが。。。 「HANDLE hMutex」と変数を宣言しただけでは何にも使えません。 CreateMutexで初めて有効な値を取得できます。その後、その値を使って排他などの制御できるようになります。 スレッドの方では渡されたDATA構造体のポインタを使用して排他制御しようとしているのか、変数がグローバールの値で、それを使用しているのかわかりませんが、どちらにしても最後にCreateMutexを行うのはロジック的にも理解できません。 あと、最後にCreateMutexして、グローバル変数のhMutexに代入し、各スレッドではその値を直接使っている場合だとしても、各スレッドの参照処理より前にCreateMutexが実行される保障はないのでご注意を。 タスクスイッチのタイミングによっては各スレッドの参照処理が先に動作することもあります。 CreateThreadの第5パラメータで、スレッドをサスペンドする必要性なども考慮する必要があります。
お礼
ありがとうございます できれば http://www.kumei.ne.jp/c_lang/sdk/sdk_92.htm をアドレスにいて手見てミューテックスの宣言の部分を見ていただきたいのですが・・・ セカンドオピニオンを得られれば鬼に金棒ですから よろしくお願いします
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
> CreateMutex 関数が返すハンドルには...ミューテックスオブジェクトのハンドルを要求する任意の関数で使うことができます。 裏を返せば、CreateMutex(あるいはOpenMutex)で得られたハンドルでなければ使えませんね。 > Mutexは宣言するだけでクリエイトしなくても使えるのか やってみました?
補足
ありがとうございます もちろんやってみました 動作を見ていても特に違いが分からないのです http://www.kumei.ne.jp/c_lang/sdk/sdk_92.htm にかかれているソースをBoralnd C++5.5 でコンパイルし実行してみましたがエラーもでず動作の違いも峻別できませんでした
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
> Mutexは宣言するだけでクリエイトしなくても使えるのか > どうかということが分からないのです ...マニュアルには何と書かれているでしょうか?
補足
ありがとうございます マニュアルには以下のようにかかれています 読解力と予備知識が欠如しているので関連部分について抽出し解説していただければ幸いです CreateMutex 関数が返すハンドルには、新しいミューテックスオブジェクトへの MUTEX_ALL_ACCESS アクセス権が割り当てられていて、ミューテックスオブジェクトのハンドルを要求する任意の関数で使うことができます。 呼び出し側プロセスの任意のスレッドは、「wait functions」(待機関数)を呼び出す際に、ミューテックスオブジェクトのハンドルを指定できます。単一オブジェクトの待機関数は、指定されたオブジェクトがシグナル状態になると制御を返します。複数オブジェクトの待機関数に対して、指定されたオブジェクトの 1 つ(またはすべて)シグナル状態になったときに、制御を返すよう指示できます。待機関数が制御を返すと、待機中のスレッドは解放され、実行が継続されます。 ミューテックスオブジェクトは、どのスレッドにも所有されていない場合はシグナル状態になります。作成側スレッドは、bInitialOwner パラメータを使うと、既存のミューテックスの所有権を即座に要求できます。ミューテックスがスレッドに所有されている場合は非シグナル状態になり、呼び出し側スレッドがそのミューテックスの所有権を要求するには待機関数(WaitForSingleObject など)を使わなければなりません。その状態でミューテックスがシグナル状態になると、待機スレッドの 1 つに所有権が割り当てられ、そのミューテックスは非シグナル状態へ変化し、待機関数は制御を返します。特定のミューテックスを所有できるスレッドは、一度に 1 つだけです。所有権を解放するには、ReleaseMutex 関数を使います。 1 つのミューテックスを所有しているスレッドは、待機関数を繰り返し呼び出す場合に、自らの実行をブロックすることなく、そのミューテックスを指定できます。通常、同じミューテックスを繰り返し待機することはないはずですが、このメカニズムは、スレッドが既に自ら所有しているミューテックスを待機しようとしてデッドロックに陥ることを防止します。ただし、このスレッドが自らの所有権を解放するには、ミューテックスが待機の条件を満たすたびに、このスレッドから ReleaseMutex 関数を呼び出さなければなりません。 複数のプロセスが CreateMutex 関数を使って、同じ名前のミューテックスを作成することもできます。最初に実行されたプロセスはそのミューテックスを実際に作成しますが、2 番目以降のプロセスは既存のミューテックスのハンドルを開くだけです。この結果、複数のプロセスが同じミューテックスに対するハンドルを取得するので、ミューテックスを作成する特定のプロセスを決定して、そのプロセスを必ず最初に起動することを保証する必要がなくなります。この手法を使う場合、bInitialOwner パラメータで FALSE を指定してください。さもないと、どのスレッドが最初の所有権を取得したのか判断しにくくなることがあります。 複数のプロセスに同じミューテックスオブジェクトのハンドルを割り当てて、プロセス間同期の目的でそのオブジェクトを使うことができます。次のようなオブジェクト共有メカニズムを利用できます。 •CreateMutex 関数の lpMutexAttributes パラメータでミューテックスオブジェクトの継承を有効にしておくと、CreateProcess 関数が作成した子プロセスは、ミューテックスオブジェクトのハンドルを継承できます。 •プロセスは、特定のミューテックスオブジェクトのハンドルを指定して DuplicateHandle 関数を呼び出すことにより、ハンドルを複製できます。他のプロセスは、そのハンドルを使うことができます。 •プロセスは、OpenMutex または CreateMutex 関数を呼び出す際に、ミューテックスオブジェクトの名前を指定できます。 ハンドルを閉じるには、CloseHandle 関数を使います。プロセスが終了する際に、システムはそのプロセスが所有していたハンドルを自動的に閉じます。ミューテックスオブジェクトに対して 1 つまたは複数のハンドルが開いている場合、最後のハンドルが閉じた時点で、そのミューテックスオブジェクトは破棄されます。
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
> とするのは正しくて/*x*/の行を削除して//をとり > hMutexの位置を前に持ってくるのは間違っているのでしょうか? 質問の意図は? そう考える根拠は何ですか?
補足
ありがとうございます Mutexは宣言するだけでクリエイトしなくても使えるのかどうかということが分からないのです Mutexが後ろにある場合はMutexをクリエイトする前にMutexを使ってます 要するにMutexは宣言しただけで使えて 必ずしもMutexを使う場合にはMutexをクリエイトするまで待ってMutexを使わなければならないのかということを知りたいのです
お礼
ありがとうございます どうもおかしいと思っていたので助かりました
補足
#include <string> using namespace std; int i_th1,i_th2; を追加しThread1&Thread2を DWORD WINAPI Thread1(LPVOID pparam) { PDATA pdata; HDC hdc; string str; char s[99]; pdata = (PDATA)pparam; while (!pdata->th_end) { WaitForSingleObject(pdata->hmutex, INFINITE); hdc = GetDC(pdata->hwnd); str="スレッド1:";str+=itoa(++i_th1,s,10); TextOut(hdc,0,0,str.c_str(), str.size()); Sleep(500); ReleaseDC(pdata->hwnd, hdc); ReleaseMutex(pdata->hmutex); } return 0L; } DWORD WINAPI Thread2(LPVOID pparam) { PDATA pdata; HDC hdc; string str; char s[99]; pdata = (PDATA)pparam; while (!pdata->th_end) { WaitForSingleObject(pdata->hmutex, INFINITE); hdc = GetDC(pdata->hwnd); str="スレッド2:";str+=itoa(++i_th2,s,10); TextOut(hdc,0,20,str.c_str(), str.size()); ReleaseDC(pdata->hwnd, hdc); ReleaseMutex(pdata->hmutex); } return 0L; } と変更したところ 後ろに宣言していたのではi_th1に対してi_th2が桁違いに大きくなっていきますが 前に宣言したらi_th1とi_th2はせいぜい1つ違いを保ちます ということで作者のケアレスミスだと思われます どうもありがとうございました