WIN32多线程四 线程同步机制Mutex

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  }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值