1. 简单多线程程序
#include <iostream>
#include <Windows.h>
#include <process.h>
using namespace std;
volatile long g_count;
const int THREADCOUNT = 10;
unsigned __stdcall thfun(void* para)
{
Sleep(100);
++g_count; //由于现将g_count读入寄存器加1,在写会内存,故要加锁
Sleep(50);
return 0;
}
int main()
{
g_count = 0;
HANDLE h[THREADCOUNT];
for (int i = 0; i < THREADCOUNT; ++i)
{
h[i] = (HANDLE)_beginthreadex(0, 0, thfun, 0, 0, 0);
}
WaitForMultipleObjects(THREADCOUNT, h, true, INFINITE);
cout<<"hello:"<<g_count<<endl;
system("pause");
return 0;
}
2. CRITICAL_SECTION
/*
*CRITICAL_SECTION具有线程所有权,同一线程可多次EnterCriticalSection
*因而只用用于线程的互斥不能用于线程的同步
*/
CRITICAL_SECTION s;
InitializeCriticalSection(&s);
EnterCriticalSection(&s);
LeaveCriticalSection(&s);
DeleteCriticalSection(&s);
第一个 CreateEvent
函数功能:创建事件
函数原型:
HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,
BOOLbManualReset,
BOOLbInitialState,
LPCTSTRlpName
);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。打个小小比方,手动置位事件相当于教室门,教室门一旦打开(被触发),所以有人都可以进入直到老师去关上教室门(事件变成未触发)。自动置位事件就相当于医院里拍X光的房间门,门打开后只能进入一个人,这个人进去后会将门关上,其它人不能进入除非门重新被打开(事件重新被触发)。
第三个参数表示事件的初始状态,传入TRUR表示已触发。
第四个参数表示事件的名称,传入NULL表示匿名事件。
第二个 OpenEvent
函数功能:根据名称获得一个事件句柄。
函数原型:
HANDLEOpenEvent(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName //名称
);
函数说明:
第一个参数表示访问权限,对事件一般传入EVENT_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示事件句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个事件。
第三个SetEvent
函数功能:触发事件
函数原型:BOOLSetEvent(HANDLEhEvent);
函数说明:每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态。
第四个ResetEvent
函数功能:将事件设为末触发
函数原型:BOOLResetEvent(HANDLEhEvent);
最后一个事件的清理与销毁
由于事件是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。
第五个PulseEvent
函数功能:将事件触发后立即将事件设置为未触发,相当于触发一个事件脉冲。
函数原型:BOOLPulseEvent(HANDLEhEvent);
函数说明:这是一个不常用的事件函数,此函数相当于SetEvent()后立即调用ResetEvent();此时情况可以分为两种:
1.对于手动置位事件,所有正处于等待状态下线程都变成可调度状态。
2.对于自动置位事件,所有正处于等待状态下线程只有一个变成可调度状态。
此后事件是末触发的。该函数不稳定,因为无法预知在调用PulseEvent ()时哪些线程正处于等待状态。
最后总结下事件Event
1.事件是内核对象,事件分为手动置位事件和自动置位事件。事件Event内部它包含一个使用计数(所有内核对象都有),一个布尔值表示是手动置位事件还是自动置位事件,另一个布尔值用来表示事件有无触发。
2.事件可以由SetEvent()来触发,由ResetEvent()来设成未触发。还可以由PulseEvent()来发出一个事件脉冲。
3.事件可以解决线程间同步问题,因此也能解决互斥问题。
详细参考:http://blog.csdn.net/morewindows/article/details/7445233
4. mutex
HANDLE s = CreateMutex(0, true, "信号量名称");//安全,true线程所有,互斥量名
HANDLE s = OpenMutex(SEMAPHORE_ALL_ACCESS, true, "信号量名称");
WaitForSingleObject(s, INFINITE);//可以根据返回值判断拥有互斥量的进程意外终止
ReleaseMutex(s);
CloseHandle(s);
1.互斥量是内核对象,它与关键段都有“线程所有权”所以不能用于线程的同步。
2.互斥量能够用于多个进程之间线程互斥问题,并且能完美的解决某进程意外终止所造成的“遗弃”问题。
5. semaphore HANDLE s = OpenSemaphore(SEMAPHORE_ALL_ACCESS, true, "信号量名称");
HANDLE s = CreateSemaphore(0, 0, 1, 0);//安全,初始资源,最大并发数,信号量名
WaitForSingleObject(s, INFINITE);
ReleaseSemaphore(s, 1, NULL);//第三个参数可以传出先前资源计数
CloseHandle(s);