事件的自動重置:兩個線層同時訪問一個函數,該函數會對全局變量進行操作,用事件進行互斥,假設這個事件初始化有信號 在經過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;
}