信号量 Semaphore:
信号量常用3个函数,使用方便:
CreateSemaphore
函数功能:创建信号量
函数原型:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数表示初始资源数量。
第三个参数表示最大并发数量。
第四个参数表示信号量的名称,传入NULL表示匿名信号量。
第二个 OpenSemaphore
函数功能:打开信号量
函数原型:
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
函数说明:
第一个参数表示访问权限,对一般传入SEMAPHORE_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示信号量句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。
第三个 ReleaseSemaphore
函数功能:递增信号量的当前资源计数
函数原型:
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
函数说明:
第一个参数是信号量的句柄。
第二个参数表示增加个数,必须大于0且不超过最大资源数量。
第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。
信号量是内核对象。
当前资源数量大于0,表示信号量处于触发,即 资源可以访问,等于0表示资源已经耗尽未触发。调用等待函数,减少信号量。
信号量为当前剩余资源数量
好吧,之前总结是错的,互斥量和临界区是无法实现的线程同步的,线程同步必须与线程互斥共用。。。这与其机制有关,互斥量和临界区都要在使用完共享资源后释放资源,而在使用资源之前等待资源可以使用,但是同步要求是等待当资源可以使用后释放一个消息通知其他线程可以按照顺序运行,但是互斥量与临界区的释放资源都是一个瞬间的过程,释放了就结束,而同步需要一个等待的函数,以等待其他资源已被其他资源释放,所以有之前的事件,以及这里使用的信号量。
信号量是一个值,其有可以使用的资源数,与互斥量相似,当信号量为0时,表示已经没有资源了,每个线程需要一定的资源以及释放一定的资源。
信号量初始化时设置初始资源数,以及最大资源数。
使用WaitForSingleObject来释放使用中的资源,一次释放一个,用ReleaseSemaphore释放信号量,一次增加使用一定数量资源。
HANDLE semaphore; CRITICAL_SECTION cs; typedef struct param{ int a; bool b; double c; string d; }; unsigned int __stdcall threadfun1(LPVOID p){ Sleep(100); EnterCriticalSection(&cs); param* funparam = (param*) p; cout<<"fun1 running:"<<funparam->d<<endl; funparam->c *= funparam->a; cout<<"ans:"<<funparam->c<<endl; LeaveCriticalSection(&cs); return 0; } DWORD __stdcall threadfun2(LPVOID p){ Sleep(100); ReleaseSemaphore(semaphore,1,NULL); EnterCriticalSection(&cs); param* funparam = (param*) p; cout<<"fun2 running:"<<funparam->d<<endl; funparam->c /= funparam->a; cout<<"Thread"<<funparam->a<<" ans:"<<funparam->c<<endl; LeaveCriticalSection(&cs); return 0; } int main(){ param p={0,true,9.995,"hello world"}; InitializeCriticalSection(&cs); semaphore = CreateSemaphore(NULL,0,1,NULL); HANDLE newthread1 = (HANDLE)_beginthreadex(NULL,0,threadfun1,&p,0,NULL); const int THREADNUM = 10; HANDLE newthread2[THREADNUM]; int &i =p.a; while(i<THREADNUM){ newthread2[i]= CreateThread(NULL,0,threadfun2,&p,0,NULL); //WaitForSingleObject(newthread2[i],INFINITE); WaitForSingleObject(semaphore,INFINITE); ; i++; } WaitForMultipleObjects(THREADNUM,newthread2,true,INFINITE); WaitForSingleObject(newthread1,INFINITE); DeleteCriticalSection(&cs); cin.get(); }研究了半天最大资源数以及一次释放多个信号的情况。对于前者,如果释放量大于最大资源数会导致无法预测的错误,而对于后者,要使用多次WaitForSingleObject(semaphore,INFINITE)来处理信号量。