C++多线程Event方法使用及实例(简单汇总)

简介:

由于多线程中event方法平时很少用到,以前偶尔用下也是临时到网上搜下代码,没有细细去理解,所以用完没几天就忘记了,今天又再次遇到需要event的问题,所以觉得有必要学习并整理下,下面是我在学习过程中百度到的两篇文章,反正我是学明白了,希望也能帮助到大家。

c++中CreateEvent函数解析

HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, 
BOOL bInitialState,
LPCSTR lpName
);
bManualReset:TRUE,使用ResetEvent()手动重置为无信号状态;FALSE,当一个等待线程被释放时,自动重置状态为无信号状态。

bInitialState:指定事件对象的初始状态,当TRUE,初始状态为有信号状态;当FALSE,初始状态为无信号状态。

下面主要演示一下采用CreateEvent实现多线程。

例子很简单,主要测试CreateEvent中bManualReset:和bInitialState参数的取值在线程调用中信号状态的情况。


测试1:

bManualReset:TRUE
bInitialState:TRUE

CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

example.cpp

 

[cpp] view plain copy 
  1. #include "iostream"

  2. #include "windows.h"

  3. usingnamespace std;  

  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);  

  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);  

  6. HANDLE hEvent = NULL;  

  7. HANDLE hThread1 = NULL;  

  8. HANDLE hThread2 = NULL;  

  9. int main(int argc, char *args[])  

  10. {  

  11.     <span style="color:#ff0000;">hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)</span>; //使用手动重置为无信号状态,初始化时有信号状态

  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

  13. //if (SetEvent(hEvent))

  14. //{

  15. //  cout << "setEvent 成功" <<endl;

  16. //}

  17.     hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);  

  18.     Sleep(200);  

  19.     hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);  

  20.     Sleep(200);  

  21. if ( NULL == hThread1)  

  22.     {  

  23.         cout <<"create thread fail!";  

  24.     }  

  25. //DWORD dCount = ResumeThread(hThread);

  26. //cout << LOWORD(dCount) << endl;

  27. return 0;  

  28. }  

  29. DWORD WINAPI ThreadProc1(LPVOID lpParam)  

  30. {  

  31.     cout <<"in thread1@!"<<endl;  

  32. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  33. if ( WAIT_OBJECT_0 == dReturn)  

  34.     {  

  35.         cout <<" thread1 signaled ! "<<endl;  

  36.     }  

  37.     cout <<"in thread1 --signal"<<endl;  

  38. //SetEvent(hEvent);

  39. return 0;  

  40. }  

  41. DWORD WINAPI ThreadProc2(LPVOID lpParam)  

  42. {  

  43.     cout <<"in thread2@!"<<endl;  

  44. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  45. if ( WAIT_OBJECT_0 == dReturn)  

  46.     {  

  47.         cout <<"thread2 signaled ! "<<endl;  

  48.     }  

  49.     cout <<"in thread2--signal"<<endl;  

  50. return 0;  

  51. }  


执行结果:  

 


从结果中看,执行完线程1又执行了线程2.

由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手动重置为无信号状态,初始化时有信号状态

所以hEvent一直处于有信号状态,无论是线程1释放后,hEvent仍处于有信号状态,所以线程2正常执行了。


测试2:

bManualReset:FALSE
bInitialState:TRUE

[cpp] view plain copy 
  1. hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

example2.cpp

[cpp] view plain copy 
  1. #include "iostream"

  2. #include "windows.h"

  3. usingnamespace std;  

  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);  

  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);  

  6. HANDLE hEvent = NULL;  

  7. HANDLE hThread1 = NULL;  

  8. HANDLE hThread2 = NULL;  

  9. int main(int argc, char *args[])  

  10. {  

  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

  12.     <span style="color:#ff0000;">hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

  13. //if (SetEvent(hEvent))

  14. //{

  15. //  cout << "setEvent 成功" <<endl;

  16. //}

  17.     hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);  

  18.     Sleep(200);  

  19.     hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);  

  20.     Sleep(200);  

  21. if ( NULL == hThread1)  

  22.     {  

  23.         cout <<"create thread fail!";  

  24.     }  

  25. //DWORD dCount = ResumeThread(hThread);

  26. //cout << LOWORD(dCount) << endl;

  27. return 0;  

  28. }  

  29. DWORD WINAPI ThreadProc1(LPVOID lpParam)  

  30. {  

  31.     cout <<"in thread1@!"<<endl;  

  32. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  33. if ( WAIT_OBJECT_0 == dReturn)  

  34.     {  

  35.         cout <<" thread1 signaled ! "<<endl;  

  36.     }  

  37.     cout <<"in thread1 --signal"<<endl;  

  38. //SetEvent(hEvent);

  39. return 0;  

  40. }  

  41. DWORD WINAPI ThreadProc2(LPVOID lpParam)  

  42. {  

  43.     cout <<"in thread2@!"<<endl;  

  44. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  45. if ( WAIT_OBJECT_0 == dReturn)  

  46.     {  

  47.         cout <<"thread2 signaled ! "<<endl;  

  48.     }  

  49.     cout <<"in thread2--signal"<<endl;  

  50. return 0;  

  51. }  

执行结果:  

 


从执行结果中分析,执行了线程1,线程2一直在等待,直到主线程结束。

由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

初始执行线程1的时候,hEvent是有信号的,所以线程1正常执行;又由于bManualReset=FALSE,所以执行完线程1后,hEvent自动重置为无信号状态,所以在线程2中,

[cpp] view plain copy 
  1. WaitForSingleObject(hEvent,INFINITE);  

函数一直在等待hEvent变为有信号状态,但是当主线程执行完,还没等待到,线程2程序一直没有走下去。  

 


测试3:

bManualReset:TRUE
bInitialState:FALSE

hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

example3.cpp

[cpp] view plain copy 
  1. #include "iostream"

  2. #include "windows.h"

  3. usingnamespace std;  

  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);  

  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);  

  6. HANDLE hEvent = NULL;  

  7. HANDLE hThread1 = NULL;  

  8. HANDLE hThread2 = NULL;  

  9. int main(int argc, char *args[])  

  10. {  

  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

  13.     <span style="color:#ff0000;">hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态</span>

  14. //if (SetEvent(hEvent))

  15. //{

  16. //  cout << "setEvent 成功" <<endl;

  17. //}

  18.     hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);  

  19.     Sleep(200);  

  20.     hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);  

  21.     Sleep(200);  

  22. if ( NULL == hThread1)  

  23.     {  

  24.         cout <<"create thread fail!";  

  25.     }  

  26. //DWORD dCount = ResumeThread(hThread);

  27. //cout << LOWORD(dCount) << endl;

  28. return 0;  

  29. }  

  30. DWORD WINAPI ThreadProc1(LPVOID lpParam)  

  31. {  

  32.     cout <<"in thread1@!"<<endl;  

  33. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  34. if ( WAIT_OBJECT_0 == dReturn)  

  35.     {  

  36.         cout <<" thread1 signaled ! "<<endl;  

  37.     }  

  38.     cout <<"in thread1 --signal"<<endl;  

  39. //SetEvent(hEvent);

  40. return 0;  

  41. }  

  42. DWORD WINAPI ThreadProc2(LPVOID lpParam)  

  43. {  

  44.     cout <<"in thread2@!"<<endl;  

  45. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  46. if ( WAIT_OBJECT_0 == dReturn)  

  47.     {  

  48.         cout <<"thread2 signaled ! "<<endl;  

  49.     }  

  50.     cout <<"in thread2--signal"<<endl;  

  51. return 0;  

  52. }  


执行结果,可想而知,只能输出:

[cpp] view plain copy 
  1. in thread1@!  

[cpp] view plain copy 
  1. in thread2@!  

因为初始为无信号状态,所以hEvent一直处于无信号状态,因此这两个线程一直在等待,直到主线程结束。  


修改:放开例子中的注释部分:

if (SetEvent(hEvent))//设置信号为有信号状态
{
cout << "setEvent 成功" <<endl;
}

执行结果:


可见,线程1和线程2都执行了。

因为调用SetEvent,事件变为有信号状态,线程1执行;又由于线程1释放后,hEvent仍旧处于有信号状态,所以线程2也执行了。


再修改:在线程1中,添加ResetEvent(hEvent)(手动设置事件为无信号状态),则线程2不会执行。


测试4:

 

bManualReset:FALSE
bInitialState:FALSE

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//线程释放后自动重置为无信号状态,初始化时为无信号状态

example4.cpp

 

[cpp] view plain copy 
  1. #include "iostream"

  2. #include "windows.h"

  3. usingnamespace std;  

  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);  

  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);  

  6. HANDLE hEvent = NULL;  

  7. HANDLE hThread1 = NULL;  

  8. HANDLE hThread2 = NULL;  

  9. int main(int argc, char *args[])  

  10. {  

  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

  13. //hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

  14.     hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

  15. if (SetEvent(hEvent))  

  16.     {  

  17.         cout << "setEvent 成功" <<endl;  

  18.     }  

  19.     hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);  

  20.     Sleep(200);  

  21.     hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);  

  22.     Sleep(200);  

  23. if ( NULL == hThread1)  

  24.     {  

  25.         cout <<"create thread fail!";  

  26.     }  

  27. //DWORD dCount = ResumeThread(hThread);

  28. //cout << LOWORD(dCount) << endl;

  29. return 0;  

  30. }  

  31. DWORD WINAPI ThreadProc1(LPVOID lpParam)  

  32. {  

  33.     cout <<"in thread1@!"<<endl;  

  34. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  35. if ( WAIT_OBJECT_0 == dReturn)  

  36.     {  

  37.         cout <<" thread1 signaled ! "<<endl;  

  38.     }  

  39.     cout <<"in thread1 --signal"<<endl;  

  40. //SetEvent(hEvent);

  41. return 0;  

  42. }  

  43. DWORD WINAPI ThreadProc2(LPVOID lpParam)  

  44. {  

  45.     cout <<"in thread2@!"<<endl;  

  46. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);  

  47. if ( WAIT_OBJECT_0 == dReturn)  

  48.     {  

  49.         cout <<"thread2 signaled ! "<<endl;  

  50.     }  

  51.     cout <<"in thread2--signal"<<endl;  

  52. return 0;  

  53. }  


执行结果:  

 


由于调用SetEvent,hEvent为有信号状态,线程1正常执行,又由于调用完线程1后,hEvent自动重置为无信号状态,所以线程2只能在等待,直到主线程退出。

修改:线程1中的SetEvent(hEvent);的注释去掉,再运行,则线程1和线程2 都会执行。










本文转自 我不会抽烟 51CTO博客,原文链接:http://blog.51cto.com/zhouhongyu1989/1225702,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
41 7
|
1月前
|
消息中间件 存储 安全
|
2月前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
26 3
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
22 2
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
24 1
|
2月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
41 1
|
2月前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
31 1
|
2月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
45 1
|
2月前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
29 1