Windows信号量使用
Ø Windows信号量可以通过以下几个函数实现:
CreateEvent: 创建信号量
WaitForSingleObject: 等待特定的信号量
ResetEvent: 重置信号量为无信号状态
SetEvent: 设置信号量为有信号状态
² 需要注意的是:
在创建信号量的时候可以指定是否自动恢复信号量,也就是在等待被唤醒后,是否自动将信号量设置为无信号状态。
当设置为自动恢复时,如果信号量被其他线程通过setEvent设置为有信号状态。如果此时没有人等待该信号量,则信号量保持有信号状态,直到第一个等待的人到达并将其设置为无信号状态为止。
如果设置为非自动恢复,此时一定要注意调用ResetEvent来将信号量恢复为无信号状态。否则其他到来的等待都将失败。
#include
#include
#include
void * Event = NULL;
static DWORD WINAPI wait (LPVOID lpParameter)
{
printf("wait for resume!\n");
WaitForSingleObject(Event, -1);
printf("resumed!\n");
ResetEvent(Event);
return0;
}
static DWORD WINAPI resume (LPVOID lpParameter)
{
printf("resume thread!\n");
SetEvent(Event);
return0;
}
int main_1()
{
HANDLEret;
Event= CreateEvent(NULL,FALSE, FALSE,NULL); //! 第二个参数表示是否手动恢复信号量,TRUE:手动恢复信号量FALSE:自动恢复信号量
test1:
ret= _beginthreadex(NULL,0, wait, NULL,0, &ret); //! 开启线程,等待该信号量
Sleep(50);
ret= _beginthreadex(NULL,0, resume, NULL,0, &ret); //! 开启线程,设置该线程为有信号状态,此时线程继续执行
Sleep(50);
ret= _beginthreadex(NULL,0, wait, NULL,0, &ret); //! 开启线程,等该该信号量。此时如果是自动恢复信号量,则该线程等待成功。否则该线程等待失败。因为在线程的设置的信号量没有被复位
Sleep(50);
test2:
ret= _beginthreadex(NULL,0, resume, NULL,0, &ret); //!开启线程,设置信号量为有信号状态
Sleep(50);
ret= _beginthreadex(NULL,0, wait, NULL,0, &ret); //! 开启线程,等待该信号量,此时因为信号量为有信号状态,线程等待失败
Sleep(50);
ret= _beginthreadex(NULL,0, wait, NULL,0, &ret); //! 开启线程,等该该信号量。此时如果是自动恢复信号量,则该线程等待成功。否则该线程等待失败。因为在线程的设置的信号量没有被复位
Sleep(50);
//!结论:信号量的复位是在调用WaitForSingleObject后进行的。也就是说假如在调用SetEvent的时候没有人等待该信号量,此时信号量并不复位。
//!而是由下一个等待该信号的人复位。这样就保证了有信号状态时总能有人使用该信号。
//!当创建的event是手动复位时,必须在适当的时候复位,否则会出错
return0;
}