ミューテックス オブジェクトの使用
ミューテックス オブジェクトを使用すると、複数のスレッドまたはプロセスによる同時アクセスから共有リソースを保護できます。 各スレッドは、共有リソースにアクセスするコードを実行する前に、ミューテックスの所有権を待機する必要があります。 たとえば、複数のスレッドがデータベースへのアクセスを共有する場合、スレッドはミューテックス オブジェクトを使用して、データベースへの書き込みを一度に 1 つのスレッドのみに許可できます。
次の例では、 CreateMutex 関数を使用してミューテックス オブジェクトを作成し、 CreateThread 関数を使用してワーカー スレッドを作成します。
このプロセスのスレッドは、データベースに書き込むときに、 まず WaitForSingleObject 関数を使用してミューテックスの所有権を要求します。 スレッドがミューテックスの所有権を取得すると、データベースに書き込み、 ReleaseMutex 関数を使用してミューテックスの所有権を解放します。
この例では、構造化例外処理を使用して、スレッドがミューテックス オブジェクトを正しく解放することを確認します。 コードの__finally ブロックは、__try ブロックが終了する方法に関係なく実行されます (__try ブロックに TerminateThread 関数の呼び出しが含まれていない場合)。 これにより、ミューテックス オブジェクトが誤って破棄されるのを防ぐことができます。
ミューテックスが破棄された場合、ミューテックスを所有していたスレッドは、終了する前にミューテックスを適切に解放しませんでした。 この場合、共有リソースの状態は不確定であり、ミューテックスを引き続き使用すると、重大なエラーになる可能性があります。 一部のアプリケーションでは、リソースを一貫した状態に復元しようとする場合があります。この例では、単にエラーを返し、ミューテックスの使用を停止します。 詳細については、「 ミューテックス オブジェクト」を参照してください。
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 2
HANDLE ghMutex;
DWORD WINAPI WriteToDatabase( LPVOID );
int main( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) WriteToDatabase,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and mutex handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghMutex);
return 0;
}
DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwCount=0, dwWaitResult;
// Request ownership of mutex.
while( dwCount < 20 )
{
dwWaitResult = WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
switch (dwWaitResult)
{
// The thread got ownership of the mutex
case WAIT_OBJECT_0:
__try {
// TODO: Write to the database
printf("Thread %d writing to database...\n",
GetCurrentThreadId());
dwCount++;
}
__finally {
// Release ownership of the mutex object
if (! ReleaseMutex(ghMutex))
{
// Handle error.
}
}
break;
// The thread got ownership of an abandoned mutex
// The database is in an indeterminate state
case WAIT_ABANDONED:
return FALSE;
}
}
return TRUE;
}