使用 Mutex 物件
您可以使用 mutex 物件 來保護共用資源,避免多個執行緒或進程同時存取。 每個執行緒都必須等候 mutex 的擁有權,才能執行可存取共用資源的程式碼。 例如,如果數個執行緒共用資料庫的存取權,執行緒可以使用 mutex 物件一次只允許一個執行緒寫入資料庫。
下列範例會使用 CreateMutex 函式來建立 mutex 物件和 CreateThread 函式來建立背景工作執行緒。
當這個進程的執行緒寫入資料庫時,它會先使用 WaitForSingleObject 函式要求 Mutex 的擁有權。 如果執行緒取得 mutex 的擁有權,它會寫入資料庫,然後使用 ReleaseMutex 函式釋放 mutex 的擁有權。
這個範例會使用結構化例外狀況處理來確保執行緒正確地釋放 mutex 物件。 不論__try區塊如何終止 (,除非__try區塊包含TerminateThread函式) 的呼叫,否則會執行程式碼__finally區塊。 這可防止不小心放棄 mutex 物件。
如果已放棄 Mutex,擁有 mutex 的執行緒在終止之前並未正確釋放。 在此情況下,共用資源的狀態不確定,而且繼續使用 Mutex 可能會遮蔽潛在的嚴重錯誤。 某些應用程式可能會嘗試將資源還原為一致狀態;此範例只會傳回錯誤,並使用 mutex 停止。 如需詳細資訊,請參閱 Mutex 物件。
#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;
}