Mutex与CriticalSection相似,都为了处理多个线程对资源的访问。区别是:mutex是内核对象,锁住mutex需要花费更多的时间,mutex可以跨进程存在。没有任何线程拥有mutex,这个mutex处于未激发状态,线程通过调用WaitForXXX来获得此mutex;除非这个线程ReleaseMutex,否则其他线程都不能获得这个mutex的拥有权。
Mutex可以用来解决哲学家就餐问题:让每个哲学家要么获得两根筷子,要么一跟筷子都不获得。哲学家就餐问题中,筷子相当于mutex,每个哲学家要么获得两个mutex,要么一个都不获得。这样就可以防止死锁的发生。
1 /*
2 * MTVERYFY.h <<Win32多线程程序设计>>作者提供的一个非常好用的宏
3 */
4 #pragma comment( lib, "USER32" )
5
6 #include <crtdbg.h>
7 #define MTASSERT(a) _ASSERTE(a)
8
9
10 #define MTVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
11
12 __inline void PrintError(LPSTR linedesc, LPSTR filename, int lineno, DWORD errnum)
13 {
14 LPSTR lpBuffer;
15 char errbuf[256];
16 #ifdef _WINDOWS
17 char modulename[MAX_PATH];
18 #else // _WINDOWS
19 DWORD numread;
20 #endif // _WINDOWS
21
22 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
23 | FORMAT_MESSAGE_FROM_SYSTEM,
24 NULL,
25 errnum,
26 LANG_NEUTRAL,
27 (LPTSTR)&lpBuffer,
28 0,
29 NULL );
30
31 wsprintf(errbuf, "\nThe following call failed at line %d in %s:\n\n"
32 " %s\n\nReason: %s\n", lineno, filename, linedesc, lpBuffer);
33 #ifndef _WINDOWS
34 WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, strlen(errbuf), &numread, FALSE );
35 Sleep(3000);
36 #else
37 GetModuleFileName(NULL, modulename, MAX_PATH);
38 MessageBox(NULL, errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
39 #endif
40 exit(EXIT_FAILURE);
41 }
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <Windows.h>
4 #include "MTVERIFY.h"
5
6 #define NUM_PHIL 5
7
8 HANDLE gChopSticks[NUM_PHIL] = {INVALID_HANDLE_VALUE}; //Mutex句柄,用来表示筷子,即哲学家们争取的资源
9 static int flag = 1;
10
11 DWORD WINAPI ThreadFunc(LPVOID); //线程函数,每个线程代表一个哲学家,哲学家们来争夺筷子(即Mutex)资源
12
13 int main()
14 {
15 int i;
16 HANDLE hPhil[NUM_PHIL];
17
18 for (i=0; i<NUM_PHIL; i++)
19 {
20 MTVERIFY( gChopSticks[i] = CreateMutex(NULL, FALSE, NULL) );
21 MTVERIFY( hPhil[i] = CreateThread(NULL, 0, ThreadFunc, (LPVOID)i, 0, NULL) );
22 }
23
24 Sleep(20000); // 主线程睡眠20000ms,这段时间内,所有哲学家想吃饭的时候,争夺筷子资源
25 flag = 0; // 标志置为0,让所有线程都正常退出
26
27 MTVERIFY( WAIT_OBJECT_0 == WaitForMultipleObjects(NUM_PHIL, hPhil, TRUE, INFINITE) );
28 for (i=0; i<NUM_PHIL; i++)
29 {
30 MTVERIFY( CloseHandle(gChopSticks[i]) );
31 MTVERIFY( CloseHandle(hPhil[i]) );
32 }
33
34 system("pause");
35 return 0;
36 }
37
38 DWORD WINAPI ThreadFunc(LPVOID n)
39 {
40 DWORD rc;
41 HANDLE myChopSticks[2];
42 int nIndex = (int)n;
43
44 while ( flag )
45 {
46 myChopSticks[0] = gChopSticks[nIndex%NUM_PHIL];
47 myChopSticks[1] = gChopSticks[(nIndex+1)%NUM_PHIL];
48
49 MTVERIFY( WAIT_OBJECT_0 == WaitForMultipleObjects(2, myChopSticks, TRUE, INFINITE) ); //哲学家等待他身边的两根筷子
50
51 printf("Philosopher # %d is eating\n", nIndex);
52 Sleep(50);
53
54 ReleaseMutex(myChopSticks[0]);
55 ReleaseMutex(myChopSticks[1]);
56 }
57
58 return (DWORD)n;
59 }