我们可以使用新的条件变量原语或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 唤醒。

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

我会选择第一个,但觉得没有理由。

最佳答案

这个特定的用例非常适合事件:这是一个一次性的过程,在此过程中必须唤醒所有等待的线程。

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

另外,正如汉斯指出的那样,Windows native 条件变量仅在Vista或更高版本上有效,因此,如果要考虑与Windows XP的兼容性,则不能使用它们。

关于c - Windows条件变量与偶数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5233681/

10-09 06:01