http://msdn.microsoft.com/en-us/library/windows/desktop/ms686927(v=vs.85).aspx
当多线程或多进程同时访问共享资源时,你可以使用mutex对象保护它们。在可以访问共享资源之前,每个线程必须等待,来获得mutex。例如,如果几个线程访问数据库,线程可以使用mutex对象,使得同时只有一个线程可以写数据库。
下面的例子,使用CreateMutex函数创建一个mutex对象,使用CreateThread函数创建工作线程。
当一个线程写数据库时,它先要使用WaitForSingleObject函数请求到mutex的所有权。如果此线程得到了mutex对象的所有权,它便 可以写数据库了,然后用ReleaseMutex函数释放所有权。
此例使用了结构化异常,确保此线程正确释放mutex对象。_finally中的代码都会执行,无论_try代码块是否正确执行。这样就阻了对mutex对象不当的操作。
如果mutex被舍弃,拥有此mutex对象的线程不可被正常的释放。在此例吕,共享资深的状态是不确定的,使用mutex对象可以产生难以理解的严重错误。一些程序可以尝试修复共享的资源。此例使用简单的方法,返回错误并停止使用mutex。更多信息,参见Mutex Objects.
#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); system("pause"); 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; }
结果
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...
Thread 2972 writing to database...
Thread 2960 writing to database...