뮤텍스 개체 사용
뮤텍스 개체를 사용하여 여러 스레드 또는 프로세스의 동시 액세스로부터 공유 리소스를 보호할 수 있습니다. 각 스레드는 공유 리소스에 액세스하는 코드를 실행하기 전에 뮤텍스의 소유권을 기다려야 합니다. 예를 들어 여러 스레드가 데이터베이스에 대한 액세스를 공유하는 경우 스레드는 뮤텍스 개체를 사용하여 한 번에 하나의 스레드만 데이터베이스에 쓸 수 있도록 허용할 수 있습니다.
다음 예제에서는 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;
}