事件的自动重置:两个线层同时访问一个函数,该函数会对全局变量进行操作,用事件进行互斥,假设这个事件初始化有信号 在经过WAITFORSIGALOBJECT()后事件就会变为没有信号,另外一个线程无法进去,第一个线程操作完需设置为有信号 setEvent(events);使事件变成有信号后,第二个线程才能进入。
事件的手动重置:相当于一个用户(线层)经过WaitForSingleObject()之后 不会使事件变为无信号,所有线层都可以进去,需要ResetEvent()使事件没有信号,下面例子使用手动重置没有意义。
互斥锁Mutex:第一个线程进入原子操作后(也就是经过waitforsingleobject()函数后) 自动锁上 然后需要ReleaseMutex(mutex);第二个线程才能进去 事件相对互斥锁可以更加细腻的控制线程
#include "iostream"
#include "windows.h"
using namespace std;
int g_iticket = 100;
unsigned long _stdcall bar(void*pramater);
//HANDLE Mutex = nullptr; //互斥锁
HANDLE hevent = nullptr;
int main(void)
{
int inum1 = 1;
int inum2 = 2;
HANDLE thread1 = CreateThread(nullptr/*安全描述符*/, 0/*建立的线程空间的大小-默认大小*/, bar/*线程函数*/, &inum1, 0/*马上开始运行*/, nullptr/"线程的名字"/);
HANDLE thread2 = CreateThread(nullptr, 0, bar, &inum2, 0, nullptr);
//HANDLE Mutex = CreateMutex(nullptr/*安全默认权限*/, false/*创建者是否为锁的拥有者*/, nullptr/*名字*/);
hevent = CreateEvent(nullptr, false/*是否手动重置*/, true/*有没有信号,有信号才能进门*/
, nullptr);//手动重置在waiforobjecket()后不会关门需要在后面加reset(event)
// hevent = CreateEvent(nullptr, false, false, nullptr);//否手动重置,初始无信号,匿名
// SetEvent(hevent); //由于初始没信号 给他一个信号
// hevent = CreateEvent(nullptr, true, true, nullptr);//是 手动重置,初始没有信号,匿名
if (thread1)
{
CloseHandle(thread1);
}
if (thread1)
{
CloseHandle(thread2);
}
Sleep(8000);
CloseHandle(hevent);
return 0;
}
unsigned long _stdcall bar(void*pramater)
{
int* inum = reinterpret_cast<int *>(pramater);
while (true)
{
WaitForSingleObject(Mutex ,INFINITE)
WaitForSingleObject(hevent, INFINITE);//等待一个人线程得到锁,得到后另一个线程阻塞在这里 进去过后就没信号
//ResetEvent(hevent);用于手动重置 //自动重置的话需要加:票0回出现~~ 应为设为自动重置的话用户经过waitforSigleObject()不会置事件无信号,所有线层都可进去
if (g_iticket > 0)
{
Sleep(50);
cout << "#" <<*inum<<":" <<g_iticket-- << endl;
//ReleaseMutex(Mutex);//第一个线程执行完过后释放这个锁好让第二个线程进入
SetEvent(hevent);
}
else
{
//ReleaseMutex(Mutex);
SetEvent(hevent);
break;
}
}
return 0;
}