ACCESS(转)经典线程同步 互斥量Mutex

翻阅本篇之前推荐阅读以下姊妹篇:

《秒杀多线程第四首一个经文的多线程同步问题》

《秒杀多线程第五首经典线程同步关键段CS》

《秒杀多线程第六首经典线程同步事件Event》

 

前介绍了关键段CS、事件Event在经典线程同步问题遭遇之采用。本篇介绍用互斥量Mutex来化解之题目。

互斥量也是一个根本对象,它之所以来担保一个线程独占一个资源的访。互斥量与根本段的表现十分相似,并且互斥量可以用来不同进程遭到之线程互斥访问资源。使用互斥量Mutex主要以因此到四只函数。下面是这些函数的原型和用验证。

第一个 CreateMutex

函数功能:创建互斥量(注意和事件Event的创函数对比)

函数原型:

HANDLECreateMutex(

  LPSECURITY_ATTRIBUTESlpMutexAttributes,

  BOOLbInitialOwner,     

  LPCTSTRlpName

);

函数说明:

先是个参数表示安全控制,一般直接传入NULL。

老二个参数用来规定互斥量的上马拥有者。如果传入TRUE表示互斥量对象中会记录创建它的线程的线程ID号并以递归计数设置也1,由于该线程ID非零,所以互斥量处于不沾状态。如果传入FALSE,那么互斥量对象中的线程ID号将安装为NULL,递归计数设置为0,这表示互斥量不也另外线程占用,处于触发状态。

老三独参数用来装互斥量的号,在差不多单过程被的线程就是通过名称来确保她访问的凡跟一个互斥量。

函数访问值:

遂返回一个意味互斥量的句柄,失败返回NULL。

 

老二只打开互斥量

函数原型:

HANDLEOpenMutex(

DWORDdwDesiredAccess,

BOOLbInheritHandle,

LPCTSTRlpName    
//名称

);

函数说明:

先是个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS。详细解释好查MSDN文档。

老二个参数表示互斥量句柄继承性,一般传入TRUE即可。

其三独参数表示称。某一个历程遭到之线程创建互斥量后,其它进程被的线程就得经者函数来找到这互斥量。

函数访问值:

成返回一个意味互斥量的句柄,失败返回NULL。

 

老三单点互斥量

函数原型:

BOOLReleaseMutex (HANDLEhMutex)

函数说明:

访互斥资源前应该要是调用等待函数,结束访时将调用ReleaseMutex()来表示友好一度收访问,其它线程可以开访问了。

 

最终一个清理互斥量

由于互斥量是根本对象,因此利用CloseHandle()就得(这或多或少具备内核对象还同)。

 

连片下去我们尽管以藏多线程问题用互斥量来确保主线程和子线程之间的联合,由于互斥量的采用函数类似于波Event,所以可以如法炮制上亦然篇之落实来写有代码:

[cpp] view
plaincopyprint?

  1. //经典线程同步问题 互斥量Mutex 
  2. #include <stdio.h> 
  3. #include <process.h> 
  4. #include <windows.h> 
  5.  
  6. long g_nNum; 
  7. unsigned int __stdcall Fun(void *pPM); 
  8. const int THREAD_NUM
    = 10; 
  9. //互斥量与重点段 
  10. HANDLE  g_hThreadParameter; 
  11. CRITICAL_SECTION g_csThreadCode; 
  12.  
  13. int main() 
  14.     printf(”     经典线程同步
    互斥量Mutex\n”); 
  15.     printf(” — by MoreWindows(
    http://blog.csdn.net/MoreWindows ) –\n\n”); 
  16.      
  17.     //初始化互斥量与第一段
    第二独参数为TRUE表示互斥量为创造线程所有 
  18.     g_hThreadParameter = CreateMutex(NULL, FALSE, NULL); 
  19.     InitializeCriticalSection(&g_csThreadCode); 
  20.  
  21.     HANDLE  handle[THREAD_NUM];  
  22.     g_nNum = 0;  
  23.     int i = 0; 
  24.     while (i < THREAD_NUM)  
  25.     { 
  26.         handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0,
    NULL); 
  27.         WaitForSingleObject(g_hThreadParameter, INFINITE); //等待互斥量被触发 
  28.         i++; 
  29.     } 
  30.     WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); 
  31.      
  32.     //销毁互斥量和要紧段 
  33.     CloseHandle(g_hThreadParameter); 
  34.     DeleteCriticalSection(&g_csThreadCode); 
  35.     for (i = 0; i < THREAD_NUM; i++) 

  36.         CloseHandle(handle[i]); 

  37.     return 0; 
  38. unsigned int __stdcall Fun(void *pPM) 
  39.     int nThreadNum = *(int *)pPM; 
  40.     ReleaseMutex(g_hThreadParameter);//触发互斥量 
  41.      
  42.     Sleep(50);//some work should to do 

  43.  

  44.     EnterCriticalSection(&g_csThreadCode); 
  45.     g_nNum++; 
  46.     Sleep(0);//some work should to do 
  47.     printf(“线程编号为%d  全局资源值为%d\n”,
    nThreadNum, g_nNum); 
  48.     LeaveCriticalSection(&g_csThreadCode); 
  49.     return 0; 
  50. }

运作结果一旦下图:

ACCESS 1

可以视,与第一段类似,互斥量也是匪可知解决线程间的并问题。

       联想到要段会记录线程ID就发生“线程拥有权”的,而互斥量也记录线程ID,莫非她吧发“线程拥有权”这同一说法。

       答案真的这样,互斥量也是发出“线程拥有权”概念的。“线程拥有权”在关键段遭受有详细的辨证,这里就不再赘言了。另外是因为互斥量常用来多进程中的线程互斥,所以它比要段还差不多一个要命有因此底表征——“遗弃”情况的处理。比如有一个占据互斥量的线程在调用ReleaseMutex()触发互斥量前即意外已了(相当给该互斥量被“遗弃”了),那么富有等待这互斥量的线程是否会面由于该互斥量无法让硌而陷入一个穿梭等待过程遭到了?这明摆着不客观。因为占用某个互斥量的线程既然已了那么好证明它不再采用让该互斥量保护之资源,所以这些资源全而该为其他线程来以。因此在这种“遗弃”情况下,系统活动将该互斥量内部的线程ID设置为0,并将其的递归计数器复置为0,表示是互斥量被点了。然后系统以“公平地”选定一个等线程来就调度(被入选的线程的WaitForSingleObject()会回到WAIT_ABANDONED_0)。

 

下面写二单程序来证明下:

先是个次创建互斥量并等待用户输入后即点互斥量。第二只次先打开互斥量,成功后便等并依据等待结果作相应的出口。详见代码:

首先单次:

[cpp] view
plaincopyprint?

  1. #include <stdio.h> 
  2. #include <conio.h> 
  3. #include <windows.h> 
  4. const char
    MUTEX_NAME[] = “Mutex_MoreWindows”; 

  5. int main() 

  6.     HANDLE hMutex = CreateMutex(NULL, TRUE,
    MUTEX_NAME); //创建互斥量 
  7.     printf(“互斥量已经创造,现在按任意键触发互斥量\n”); 

  8.     getch(); 

  9.     //exit(0); 
  10.     ReleaseMutex(hMutex); 
  11.     printf(“互斥量已经点\n”); 
  12.     CloseHandle(hMutex); 
  13.     return 0; 

亚只次:

[cpp] view
plaincopyprint?

  1. #include <stdio.h> 
  2. #include <windows.h> 
  3. const char
    MUTEX_NAME[] = “Mutex_MoreWindows”; 

  4. int main() 

  5.     HANDLE hMutex =
    OpenMutex(MUTEX_ALL_ACCESS, TRUE, MUTEX_NAME); //打开互斥量 
  6.     if (hMutex == NULL) 
  7.     { 
  8.         printf(“打开互斥量失败\n”); 
  9.         return 0; 
  10.     } 
  11.     printf(“等待中….\n”); 
  12.     DWORD dwResult =
    WaitForSingleObject(hMutex, 20 * 1000); //等待互斥量被触发 
  13.     switch (dwResult) 
  14.     { 
  15.     case WAIT_ABANDONED: 
  16.         printf(“拥有互斥量的历程意外已\n”); 

  17.         break; 

  18.  
  19.     case WAIT_OBJECT_0: 
  20.         printf(“已经吸收信号\n”); 
  21.         break; 
  22.  
  23.     case WAIT_TIMEOUT: 
  24.         printf(“信号不以确定之日内送至\n”); 

  25.         break; 

  26.     } 
  27.     CloseHandle(hMutex); 
  28.     return 0; 
  29. }  

以就第二单程序时如优先启动程序往往启动程序二。下面展示部分输出结果:

结果一.二个经过顺利执行完毕:

ACCESS 2

结果二.拿先后一中//exit(0);前面的笺注符号去丢,这样程序一样当点互斥量之前即会盖执行exit(0);语句以脱离,程序二会面吸纳WAIT_ABANDONED消息并出口“拥有互斥量的经过意外已”:

ACCESS 3

来是针对“遗弃”问题之处理,在多进程被的线程同步啊得以放心的采取互斥量。

 

末总结下互斥量Mutex:

1.互斥量是水源对象,它同主要段都有“线程所有权”所以不能够用于线程的联合。

2.互斥量能够用于多只经过中线程互斥问题,并且能圆的化解有经过意外已所造成的“遗弃”问题。

 

下一篇《秒杀多线程第八首 经典线程同步
信号量Semaphore》将介绍以信号量Semaphore来化解之经典线程同步问题。

 

 

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7470936

比方认为本文对你发出赞助,请点击‘顶’支持一下,您的支持是自我撰文最特别之动力,谢谢。

相关文章