6

我们可以使用新的条件变量原语或Windows事件来同步WinNT v6.x或更高版本中的线程。考虑以下两种方法,我们希望工作人员在main中设置“go”时同时运行,否则应全部阻止。Windows条件变量与事件

/*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

哪一个在实践中更好,只关于开销? (提示:上下文切换锁争开销阻塞线程)的

我会选择第一个,但感觉缺乏理由的。

回答

5

这个特殊的用例非常适用于一个事件:它是一个一次性过程,所有等待的线程都必须被唤醒。

条件变量更适合于像队列这样的事情,在等待线程被唤醒时,有一个关联的谓词可能或不可能是真的(例如队列中的项目---它们可能已被另一个线程),或者重要的是线程唤醒的是那些已经等待条件变量通知的人,而不是之后出现的线程。

正如Hans指出的那样,Windows本机条件变量仅适用于Vista或更高版本,因此如果与Windows XP兼容性受到关注,则无法使用它们。

2

支持条件变量需要Vista或更高版本。通常情况下,降压停止的地方,支持XP不幸的是仍然很重要。你的第二个片段也有很大的优势,它是微不足道的理解。我不知道你在第一个尝试做什么,它看起来是错误的。