我们可以使用新的条件变量原语或windows事件来同步WinNT v6.x或更高版本中的线程。考虑以下两种方法,我们希望工人在main中设置“go”的同时运行,否则它们都应该阻塞。
/*language C code*/
/*Windows Condition Variable*/
int go=0;
CONDITION_VARIABLE cv;
SRWLOCK lock;
void workers()
{
AcquireSRWLockShared(&lock);
if(go==0)
{
SleepConditionVariableSRW(&cv, &lock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
}
ReleaseSRWLockShared(&lock);
/*
Workers continue...
*/
}
void main()
{
int i;
InitializeConditionVariable(&cv);
InitializeSRWLock(&lock);
for(i=0;i<10;i++)
{
CreateThread(0, 0, workers, 0, 0, 0);
}
AcquireSRWLockExclusive(&lock);
go=1;
ReleaseSRWLockExclusive(&lock);
WakeAllConditionVariable(&cv);
}
或
/*language C code*/
/*Windows Event*/
HANDLE go;
void workers()
{
WaitForSingleObject(go, INFINITE);
/*
Workers continue...
*/
}
void main()
{
int i;
go=CreateEvent(0,1,0,0); /*No security descriptor, Manual Reset, initially 0, no name*/
for(i=0;i<10;i++)
{
CreateThread(0, 0, workers, 0, 0, 0);
}
SetEvent(go);
}
在第一种方法中,工作人员被 SleepConditionVariableSRW 阻止,并被 WakeAllConditionVariable 唤醒。在第二个中,它们在 WaitForSingleObject 上被阻止,并被 SetEvent 唤醒。
哪一个在实践中更好,只考虑开销? (提示:上下文切换,锁争用,阻塞线程的开销)
我会选择第一个但感觉缺乏理由。
答案 0 :(得分:5)
这个特殊用例非常适合事件:它是一次性过程,必须唤醒所有等待的线程。
条件变量更适合于队列之类的东西,其中有一个关联的谓词在等待的线程唤醒时可能或不成立(例如队列中的项目 - 它们可能已被另一个线程使用)或者,当通知条件变量时,被唤醒的线程是那些已经等待的线程之一,而不是之后出现的线程。
另外,正如Hans所指出的,Windows本机条件变量仅适用于Vista或更高版本,因此如果与Windows XP的兼容性受到关注,则无法使用它们。
答案 1 :(得分:2)
支持条件变量需要Vista或更好。这通常是降压停止的地方,不幸的是支持XP往往仍然很重要。你的第二个片段确实具有相当大的优势,可以理解它是微不足道的。我不清楚你在第一个尝试做什么,看起来不对。