Windows 条件变量与事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5233681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:22:00  来源:igfitidea点击:

Windows Condition Variable vs. Event

cwindowsmultithreadingcondition-variablereaderwriterlockslim

提问by Y.Z

We can use either the new condition variable primitive or windows event in order to synchronize threads in WinNT v6.x or later. Consider the following two approaches, we want workers to run at the same time when "go" is set in main, otherwise they should all block.

我们可以使用新的条件变量原语或 windows 事件来同步 WinNT v6.x 或更高版本中的线程。考虑以下两种方法,我们希望在main中设置“go”的同时让worker同时运行,否则它们都应该阻塞。

/*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);
}

or

或者

/*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);
}

In the first approach, workers are blocked on SleepConditionVariableSRWand woke up by WakeAllConditionVariable. In the second, they are blocked on WaitForSingleObjectand woke up by SetEvent.

在第一种方法,工人封锁SleepConditionVariableSRW和醒来WakeAllConditionVariable。在第二个中,它们被WaitForSingleObject阻塞并被SetEvent唤醒。

Which one is better in practice, only regarding overhead? (hint: context switch, lock contention, overhead of blocking threads)

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

I would choose the first but feel lack of justification.

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

采纳答案by Anthony Williams

This particular use case is ideal for an event: it's a one-shot process, where all waiting threads must be woken.

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

Condition variables are better suited for things like queues, where there is an associated predicate that may or not be true when the waiting thread wakes up (such as items on the queue --- they may have been consumed by another thread), or where it matters that the thread woken is one of those already waiting when the condition variable is notified, rather than one that comes along afterwards.

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

Plus, as Hans pointed out, Windows native condition variables only work on Vista or later, so you can't use them if compatibility with Windows XP is a concern.

另外,正如 Hans 所指出的,Windows 本机条件变量仅适用于 Vista 或更高版本,因此如果需要考虑与 Windows XP 的兼容性,则无法使用它们。

回答by Hans Passant

Support for condition variables requires Vista or better. That's usually where the buck stops, supporting XP unfortunately tends to be still important. Your second snippet also does has the considerable advantage that it is trivial to understand. I don't have a clue what you're trying to do in the first one, it looks wrong.

对条件变量的支持需要 Vista 或更高版本。这通常是降压停止的地方,不幸的是,支持 XP 往往仍然很重要。您的第二个代码段也具有相当大的优势,即它很容易理解。我不知道你在第一个中想要做什么,它看起来是错误的。