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

开卷本篇在此之前推荐阅读以下姊妹篇:

秒杀二十四线程第4篇一个经典的三十六线程同步难题

秒杀二十多线程第六篇经典线程同步关键段CS

秒杀多线程第四篇经典线程同步事件伊夫nt

 

前方介绍了关键段CS事件Event经文线程同步难点中的使用。本篇介绍用互斥量Mutex来缓解那一个难点。

互斥量也是2个水源对象,它用来确认保证一个线程独占三个财富的走访。互斥量与根本段的行为极度相似,并且互斥量能够用来差别进度中的线程互斥访问财富。使用互斥量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文书档案。

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

其七个参数表示名称。某两个经过中的线程创制互斥量后,其余进度中的线程就足以通过这些函数来找到这些互斥量。

函数访问值:

得逞再次回到1个象征互斥量的句柄,失利再次回到NULL。

 

其多个触发互斥量

函数原型:

BOOLReleaseMutex (HANDLEhMutex)

函数表明:

做客互斥能源前应该要调用等待函数,截至访问时就要调用ReleaseMutex()来表示友好早就收尾访问,别的线程可以起来访问了。

 

最终1个清理互斥量

鉴于互斥量是水源对象,因而使用CloseHandle()就足以(这或多或少持有内核查象都相同)。

 

接下去大家就在经典四线程难题用互斥量来担保主线程与子线程之间的协同,由于互斥量的使用函数类似于事件伊夫nt,所以能够照猫画虎上一篇的兑现来写出代码:

[cpp] view
plain
copyprint?

  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,表示这些互斥量被触发了。然后系统将“公平地”选定1个守候线程来成功调度(被入选的线程的WaitForSingleObject()会回到WAIT_ABANDONED_0)。

 

上边写2个程序来验证下:

第5个程序成立互斥量并等候用户输入后就接触互斥量。第二个程序先打开互斥量,成功后就等候并依照等待结果作相应的出口。详见代码:

第①个程序:

[cpp] view
plain
copyprint?

  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
plain
copyprint?

  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 * 一千); //等待互斥量被触发 
  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

假如以为本文对你有匡助,请点击‘顶’帮衬一下,您的支撑是自家写作最大的重力,谢谢。

相关文章