C语言中,事件对象(CreateEvent)、互斥对象(CreateMutex)、关键代码段(InitializeCriticalSection)

 事件对象(CreateEvent)、互斥对象(CreateMutex)、关键代码段(InitializeCriticalSection)都是保证数据安全的一些措施。

1、互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,速度较慢,但可以实现在多个进程中各线程间进行同步

2、关键代码段式工作在用户方式下,同步速度较快,但在使用关键代码段时,很容易进入死锁状态,因为在进入关键代码时无法设定超时值。

     MFC下InitializeCriticalSection()和DeleteCriticalSection()可以放在类的构造函数和析构函数中


CreateEvent

代码实例1.1 Event

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. HANDLE hEvent;  
  12.   
  13. int main()  
  14. {  
  15.     HANDLE hthread1,hthread2;  
  16.     ////the third parameter: 指定事件对象的初始状态。  
  17.     /// 如果为TRUE,初始状态为有信号状态; FALSE:为无信号状态。  
  18.     /// the second parameter: TRUE:人工重置,否则自动重置无信号状态  
  19.     hEvent=CreateEvent(NULL,FALSE,FALSE,_T("tickets"));    
  20.     if(hEvent)  
  21.     {  
  22.         if(ERROR_ALREADY_EXISTS==GetLastError()) //当前有实例在  
  23.         {  
  24.             cout<<"only instance can run\n";  
  25.         }  
  26.     }  
  27.     SetEvent(hEvent);  ///set 有信号状态  
  28.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  29.     //  Sleep(11);  
  30.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  31.       
  32.     //  while(1)  
  33.     Sleep(10000);  
  34.     CloseHandle(hthread1);//关闭句柄并不终止程序  
  35.     CloseHandle(hthread2);  
  36.     CloseHandle(hEvent);  
  37.     return 0;  
  38. }  
  39.   
  40. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  41. {  
  42.     while(1)  
  43.     {   ///请求到信号,系统自动重置为无信号状态  
  44.         WaitForSingleObject(hEvent,INFINITE);    
  45.         if(tickets>0)  
  46.         {  
  47.             cout<<"thread 1: "<<tickets--<<endl;  
  48.             Sleep(50);  
  49.         }  
  50.         else  
  51.             break;  
  52.         SetEvent(hEvent);  //set 有信号状态  
  53.     }  
  54.     return 0;  
  55. }  
  56.   
  57. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  58. {  
  59.     while(1)  
  60.     {  
  61.         WaitForSingleObject(hEvent,INFINITE); /////请求到信号,系统重置为无信号状态  
  62.         if(tickets>0)  
  63.         {  
  64.             cout<<"thread 2: "<<tickets--<<endl;  
  65.             Sleep(10);  
  66.         }  
  67.         else  
  68.             break;  
  69.         SetEvent(hEvent);  ////set 有信号状态  
  70.     }  
  71.     return 0;  
  72. }  

执行结果:



代码实例1.2 无 Event 

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. HANDLE hEvent;  
  12.   
  13. int main()  
  14. {  
  15.     HANDLE hthread1,hthread2;  
  16.     ////the third parameter: 指定事件对象的初始状态。  
  17.     /// 如果为TRUE,初始状态为有信号状态; FALSE:为无信号状态。  
  18.     /// the second parameter: TRUE:人工重置,否则自动重置无信号状态  
  19.     //hEvent=CreateEvent(NULL,FALSE,FALSE,_T("tickets"));    
  20.     //if(hEvent)  
  21.     {  
  22.         if(ERROR_ALREADY_EXISTS==GetLastError()) //当前有实例在  
  23.         {  
  24.             cout<<"only instance can run\n";  
  25.         }  
  26.     }  
  27.     //SetEvent(hEvent);  ///set 有信号状态  
  28.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  29.     //  Sleep(11);  
  30.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  31.       
  32.     //  while(1)  
  33.     Sleep(10000);  
  34.     CloseHandle(hthread1);  
  35.     CloseHandle(hthread2);  
  36.     CloseHandle(hEvent);  
  37.     return 0;  
  38. }  
  39.   
  40. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  41. {  
  42.     while(1)  
  43.     {   ///请求到信号,系统自动重置为无信号状态  
  44.         //WaitForSingleObject(hEvent,INFINITE);    
  45.         if(tickets>0)  
  46.         {  
  47.             cout<<"thread 1: "<<tickets--<<endl;  
  48.             Sleep(30);  
  49.         }  
  50.         else  
  51.             break;  
  52.         //SetEvent(hEvent);  //set 有信号状态  
  53.     }  
  54.     return 0;  
  55. }  
  56.   
  57. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  58. {  
  59.     while(1)  
  60.     {  
  61.         //WaitForSingleObject(hEvent,INFINITE); /////请求到信号,系统重置为无信号状态  
  62.         if(tickets>0)  
  63.         {  
  64.             cout<<"thread 2: "<<tickets--<<endl;  
  65.             Sleep(10);  
  66.         }  
  67.         else  
  68.             break;  
  69.         //SetEvent(hEvent);  ////set 有信号状态  
  70.     }  
  71.     return 0;  
  72. }  




代码实例 2.1 有 Mutex

[cpp]  view plain  copy
  1. #include "StdAfx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. HANDLE hMutex;  
  12.   
  13. int main()  
  14. {  
  15.     HANDLE hthread1,hthread2;  
  16.     hMutex=CreateMutex(NULL,FALSE,_T("tickets"));  ///TRUE :main thread got mutex object  
  17.   
  18.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  19.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  20.     CloseHandle(hthread1);  
  21.     CloseHandle(hthread2);  
  22.   
  23.     if(hMutex)  
  24.     {  
  25.         if(ERROR_ALREADY_EXISTS==GetLastError())  
  26.         {  
  27.             cout<<"only instance can run!"<<endl;  
  28.             return 0;  
  29.         }  
  30.     }  
  31.   
  32.   
  33.     Sleep(10000);  
  34.       
  35.     return 0;  
  36. }  
  37.   
  38. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  39. {  
  40.     while(1)  
  41.     {  
  42.         WaitForSingleObject(hMutex,INFINITE);  
  43.         if(tickets>0)  
  44.         {  
  45.             Sleep(30);  
  46.             cout<<"thread 1: "<<tickets--<<endl;  
  47.         }  
  48.         else  
  49.             break;  
  50.         ReleaseMutex(hMutex);  //释放当前线程ID,互斥对象计数器-1  
  51.     }  //谁拥有互斥对象,你可以释放  
  52.     return 0;  
  53. }  
  54.   
  55. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  56. {  
  57.     while(1)  
  58.     {  
  59.         WaitForSingleObject(hMutex,INFINITE);  
  60.         if(tickets>0)  
  61.         {  
  62.             Sleep(10);  
  63.             cout<<"thread 2: "<<tickets--<<endl;  
  64.         }  
  65.         else  
  66.             break;  
  67.         ReleaseMutex(hMutex);  
  68.     }  
  69.     return 0;  
  70. }  

执行结果 :


代码实例 2.2 无Mutex

[cpp]  view plain  copy
  1. #include "StdAfx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. HANDLE hMutex;  
  12.   
  13. int main()  
  14. {  
  15.     HANDLE hthread1,hthread2;  
  16.     //hMutex=CreateMutex(NULL,FALSE,_T("tickets"));  ///TRUE :main thread got mutex object  
  17.   
  18.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  19.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  20.     CloseHandle(hthread1);  
  21.     CloseHandle(hthread2);  
  22.   
  23.     //if(hMutex)  
  24.     {  
  25.         if(ERROR_ALREADY_EXISTS==GetLastError())  
  26.         {  
  27.             cout<<"only instance can run!"<<endl;  
  28.             return 0;  
  29.         }  
  30.     }  
  31.   
  32.   
  33.     Sleep(10000);  
  34.       
  35.     return 0;  
  36. }  
  37.   
  38. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  39. {  
  40.     while(1)  
  41.     {  
  42.         //WaitForSingleObject(hMutex,INFINITE);  
  43.         if(tickets>0)  
  44.         {  
  45.             Sleep(30);  
  46.             cout<<"thread 1: "<<tickets--<<endl;  
  47.         }  
  48.         else  
  49.             break;  
  50.         //ReleaseMutex(hMutex);  //释放当前线程ID,互斥对象计数器-1  
  51.     }  //谁拥有互斥对象,你可以释放  
  52.     return 0;  
  53. }  
  54.   
  55. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  56. {  
  57.     while(1)  
  58.     {  
  59.         //WaitForSingleObject(hMutex,INFINITE);  
  60.         if(tickets>0)  
  61.         {  
  62.             Sleep(10);  
  63.             cout<<"thread 2: "<<tickets--<<endl;  
  64.         }  
  65.         else  
  66.             break;  
  67.         //ReleaseMutex(hMutex);  
  68.     }  
  69.     return 0;  
  70. }  




关键代码段3.1:

[cpp]  view plain  copy
  1. #include "StdAfx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. CRITICAL_SECTION g_cs;  /*---    
  12.                         每个线程中访问临界资源的那段程序称为临界区(Critical Section) 
  13.                         (临界资源是一次仅允许一个线程使用的共享资源)。 
  14.                         每次只准许一个线程进入临界区,进入后不允许其他线程进入。 
  15.                         不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问. 
  16.                         ------------------**/  
  17. int main()  
  18. {  
  19.     HANDLE hthread1,hthread2;  
  20.     InitializeCriticalSection(&g_cs);  
  21.   
  22.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  23.     //  Sleep(11);  
  24.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  25.     CloseHandle(hthread1);  
  26.     CloseHandle(hthread2);  
  27.   
  28.     //  while(1)  
  29.     Sleep(4000);  
  30.     DeleteCriticalSection(&g_cs);  
  31.   
  32.     return 0;  
  33. }  
  34.   
  35. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  36. {  
  37.     while(1)  
  38.     {     
  39.         EnterCriticalSection(&g_cs);  //进入关键代码段  
  40.         if(tickets>0)  
  41.         {  
  42.             Sleep(10);  
  43.             cout<<"thread 1: "<<tickets--<<endl;  
  44.         }  
  45.         else  
  46.             break;  
  47.         LeaveCriticalSection(&g_cs);//释放临界区对象所有权  
  48.         Sleep(5);  
  49.     }  
  50.     return 0;  
  51. }  
  52.   
  53. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  54. {  
  55.     while(1)  
  56.     {  
  57.         EnterCriticalSection(&g_cs); /////请求到信号,系统重置为无信号状态  
  58.         if(tickets>0)  
  59.         {  
  60.             Sleep(10);  
  61.             cout<<"thread 2: "<<tickets--<<endl;  
  62.         }  
  63.         else  
  64.             break;  
  65.         LeaveCriticalSection(&g_cs);  
  66.         Sleep(15);  
  67.     }  
  68.     return 0;  
  69. }  

执行结果 :


代码实例:无代码段约束3.2

[cpp]  view plain  copy
  1. #include "StdAfx.h"  
  2. #include <iostream>  
  3. #include <windows.h>  
  4.   
  5. using namespace std;  
  6.   
  7. DWORD WINAPI thread1fun(LPVOID);  
  8. DWORD WINAPI thread2fun(LPVOID);  
  9.   
  10. int tickets=20;  
  11. CRITICAL_SECTION g_cs;  /*---    
  12.                         每个线程中访问临界资源的那段程序称为临界区(Critical Section) 
  13.                         (临界资源是一次仅允许一个线程使用的共享资源)。 
  14.                         每次只准许一个线程进入临界区,进入后不允许其他线程进入。 
  15.                         不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问. 
  16.                         ------------------**/  
  17. int main()  
  18. {  
  19.     HANDLE hthread1,hthread2;  
  20.     //InitializeCriticalSection(&g_cs);  
  21.   
  22.     hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  
  23.     //  Sleep(11);  
  24.     hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  
  25.     CloseHandle(hthread1);  
  26.     CloseHandle(hthread2);  
  27.   
  28.     //  while(1)  
  29.     Sleep(4000);  
  30.     //DeleteCriticalSection(&g_cs);  
  31.   
  32.     return 0;  
  33. }  
  34.   
  35. DWORD WINAPI thread1fun(LPVOID lpParameter)  
  36. {  
  37.     while(1)  
  38.     {     
  39.         //EnterCriticalSection(&g_cs);  //进入关键代码段  
  40.         if(tickets>0)  
  41.         {  
  42.             Sleep(10);  
  43.             cout<<"thread 1: "<<tickets--<<endl;  
  44.         }  
  45.         else  
  46.             break;  
  47.         //LeaveCriticalSection(&g_cs);//释放临界区对象所有权  
  48.         Sleep(5);  
  49.     }  
  50.     return 0;  
  51. }  
  52.   
  53. DWORD WINAPI thread2fun(LPVOID lpParameter)  
  54. {  
  55.     while(1)  
  56.     {  
  57.         //EnterCriticalSection(&g_cs); /////请求到信号,系统重置为无信号状态  
  58.         if(tickets>0)  
  59.         {  
  60.             Sleep(10);  
  61.             cout<<"thread 2: "<<tickets--<<endl;  
  62.         }  
  63.         else  
  64.             break;  
  65.         //LeaveCriticalSection(&g_cs);  
  66.         Sleep(15);  
  67.     }  
  68.     return 0;  
  69. }  


转载于https://blog.csdn.net/makenothing/article/details/43269151

猜你喜欢

转载自blog.csdn.net/qq_31094099/article/details/80307113
今日推荐