利用CreateEvent 实现简单的 —— 线程同步
程序员文章站
2022-04-02 22:56:58
...
—— 除夕前一天,最近大家都要注意安全哟 ~
线程同步
当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该进程完成操作,其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。
我们将使用 CreateEvent 来创建一个内核对象,管理线程进行同步操作。
假设我们有20个苹果,那么运行原理如下图所示:
大家都知道,互斥在某一时段是只执行一个线程的,但是互斥是没有序的
,也就是说如果我们用互斥来实现上面的情况,可能会出现下面这种可能:
这种情况是很有可能发生的。
如果我们在互斥的前提下,再加上有序,那不就可以实现我们需要的同步操作了吗 ?
代码实现
我们将用代码来实现线程的同步操作,其中大部分代码都加了注释 , 里面有些API的参数没有注释,可找度娘查阅
:
#include <Windows.h> // 调用 win32的API
#include <iostream>
using namespace std;
// 创建两个事件 所获得的句柄 名字随便取
HANDLE hUa;
HANDLE mEng;
// 定义两个线程回调函数 用于测试线程同步
// 第一个线程执行函数
DWORD WINAPI ThreadFunc1(LPVOID lp)
{
for(int i = 0; i < 10; ++i)
{
// 获取事件信号
WaitForSingleObject(hUa, INFINITE); // 如果没有信号,则不会浪费CPU为他分配的资源,直接执行其他的线程代码
Sleep(500);
cout << "---------- " << i << endl;
SetEvent(mEng); // **另一个事件的信号,并将自己设置为无信号,这样每次只能执行一次循环
}
return 0;
}
// 第二个线程执行函数
DWORD WINAPI ThreadFunc2(LPVOID lp)
{
for(int i = 0; i < 10; ++i)
{
// 重要的事情再说一次
// 获取事件信号
WaitForSingleObject(mEng, INFINITE); // 如果没有信号,则不会浪费CPU为他分配的资源,直接执行其他的线程代码
Sleep(500);
cout << "++++++++++ " << i << endl;
SetEvent(hUa); // **另一事件的信号,并将自己设置为无信号,这样每次只能执行一次循环
}
return 0;
}
int main()
{
// 创建两个事件
/*
这里说一下这个API 的第三个参数:
1. TRUE --> 有信号
2. FALSE --> 无信号
这样一开始只能执行第一个线程的代码,第二个线程等待信号方可执行
*/
hUa = CreateEvent(NULL, FALSE, TRUE, NULL);
mEng = CreateEvent(NULL, FALSE, FALSE, NULL);
// 创建两个线程
HANDLE hd[2];
hd[0] = CreateThread(NULL, 0, ThreadFunc1, NULL, 0, NULL);
hd[1] = CreateThread(NULL, 0, ThreadFunc2, NULL, 0, NULL);
// 等待两个创建的线程结束,否则main里执行的线程很快就结束了,防止程序一闪而过
WaitForMultipleObjects(2, hd, TRUE, INFINITE);
// 关闭一些句柄
CloseHandle(hUa);
CloseHandle(mEng);
CloseHandle(hd[0]);
CloseHandle(hd[1]);
return 0;
}
运行效果如下:
---------- 0
++++++++++ 0
---------- 1
++++++++++ 1
---------- 2
++++++++++ 2
---------- 3
++++++++++ 3
---------- 4
++++++++++ 4
---------- 5
++++++++++ 5
---------- 6
++++++++++ 6
---------- 7
++++++++++ 7
---------- 8
++++++++++ 8
---------- 9
++++++++++ 9
新的一年,愿各位开心生活每一天,虽然感觉特别难……
^ _ ^
上一篇: win32基本控件
下一篇: 《数据结构》课程设计 之 哈希查找