windows 在多线程应用程序中等待变量的最佳方法是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2060200/
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 13:44:46  来源:igfitidea点击:

What is the best way to wait for a variable in a multithreaded application

c++cwindowswinapiresources

提问by T.T.T.

I would like to do something like the below for a multi-threaded program:

我想为多线程程序执行如下操作:

// wait for variable to become true but don't hog resources  
// then re-sync queues  

Is something like thisa good solution?

这样的事情是一个很好的解决方案吗?

while (!ready) {
    Thread.Sleep(250); // pause for 1/4 second;
};

回答by Nikolai Fetissov

No, this is not a good solution. First it might sleep too long. Second it's easy for threads to get into lockstep. Here's couple of links to MSDN articles on proper synchronization techniques:

不,这不是一个好的解决方案。首先它可能睡得太久了。其次,线程很容易进入锁步。以下是有关正确同步技术的 MSDN 文章的几个链接:

回答by Emile Cormier

Here's how you do it using boost:

以下是使用 boost 的方法:

boost::condition_variable condvar;
boost::mutex mutex;
bool finished1 = false;
bool finished2 = false;

void longComputation1()
{
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished1 = false;
    }
    // Perform long computation
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished1 = true;
    }
    condvar.notify_one();
}

void longComputation2()
{
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished2 = false;
    }
    // Perform long computation
    {
        boost::lock_guard<boost::mutex> lock(mutex);
        finished2 = true;
    }
    condvar.notify_one();
}

void somefunction()
{
    // Wait for long computations to finish without "spinning"
    boost::lock_guard<boost::mutex> lock(mutex);
    while(!finished1 && !finished2)
    {
        condvar.wait(lock);
    }

    // Computations are finished
}

For the sake of brevity, I didn't include the thread spawning code.

为简洁起见,我没有包含线程生成代码。

The boost::lock_guarduses the RAII idiom to automatically unlock the mutex when the lock object goes out of scope. Very useful for preventing deadlocks in case of exceptions.

boost::lock_guard使用RAII成语当锁定对象超出范围出自动解锁互斥。在异常情况下防止死锁非常有用。

I find condition variables less error prone than Microsoft's Event objects. If you use boost.Thread, you'll have the added benefit of cross-platform potability.

我发现条件变量比 Microsoft 的 Event 对象更不容易出错。如果您使用 boost.Thread,您将获得跨平台可移植性的额外好处。

回答by Andrey Shvydky

Try to use Event(kernel object) instead of simple variable and replace your loop by:

尝试使用事件(内核对象)而不是简单变量,并通过以下方式替换循环:

WaitForSingleObject(hEventHandle, INFINITE);

回答by phatmanace

The code above will work, and maybe appropriate in some circumstances.

上面的代码可以工作,并且在某些情况下可能是合适的。

You could also look at a critical section or semaphore - this will make your application block and wait until the resource becomes available,

您还可以查看临界区或信号量 - 这将使您的应用程序阻塞并等待资源可用,

Your thread that does the work grabs the mutex, does some work, meanwhile, the main method also tries to grab the same mutex, but can't. when the worker thread(s) exit, they release the mutex and your main thread can pass the critical section and continue.

您执行工作的线程会抓取互斥锁,并执行一些工作,同时,主要方法也尝试抓取相同的互斥锁,但不能。当工作线程退出时,它们会释放互斥锁,您的主线程可以通过临界区并继续。

回答by Alexander Gessler

First of all, you need to declare your 'ready' variable at least 'volatile' or this could have nasty side effects. Secondly, sleeping thatlong vefore reevaluating the condition is only a good idea if the duration it might take is indeed very long, let's say a few minutes.

首先,您需要至少将“就绪”变量声明为“易失性”,否则这可能会产生令人讨厌的副作用。其次,重新评估病情之前睡那么久只是一个好主意,如果它可能需要的持续时间确实很长,比如说几分钟。

Using the WinAPI's Event functions (CreateEvent, SetEvent(), WaitForSingleEvent()) is the best way to do it. Of course it introduces some overhead, but usually it's fine.

使用 WinAPI 的事件函数 ( CreateEvent, SetEvent(), WaitForSingleEvent()) 是最好的方法。当然它会引入一些开销,但通常没问题。

If you want to stick with your solution, looping and rechecking the condition a few times before you sleep again could improve performance in some scenarios.

如果你想坚持你的解决方案,在你再次睡觉之前循环并重新检查条件几次可以提高某些情况下的性能。

回答by HostileFork says dont trust SE

The raw Win32 API has EVENT for doing this, here's a usage example:

原始 Win32 API 具有用于执行此操作的 EVENT,这是一个用法示例:

http://msdn.microsoft.com/en-us/library/ms686915(VS.85).aspx

http://msdn.microsoft.com/en-us/library/ms686915(VS.85).aspx

However, that API is C-oriented and particular to Windows. If writing a C++ program you might consider making your code more platform independent by using something like boost::threads, which has an analogue in Conditions.

但是,该 API 是面向 C 的,并且特别适用于 Windows。如果编写 C++ 程序,您可能会考虑使用 boost::threads 之类的东西使您的代码更加独立于平台,它在条件中具有类似物。

A caveat I've found is that Windows can WaitForMultipleObjects, thus waiting on several events (and other handle classes) at a time. boost has no parallel AFAIK.

我发现的一个警告是 Windows 可以WaitForMultipleObjects,因此一次等待多个事件(和其他句柄类)。boost 没有平行的 AFAIK。

回答by Steve Townsend

On top of good answers already provided - you will waste half the sleep time, assuming a random distribution of the occurrence you wish to detect. 125ms is an eternity in computer time.

除了已经提供的好答案之外 - 假设您希望检测的事件随机分布,您将浪费一半的睡眠时间。125ms 是计算机时间的永恒。

WaitForSingleObject on a Win32 Event handle allows you to detect the required signal pseudo-immediately (depending on what other threads in your process are doing), and not do redundant checks (how many needless loops do you have to execute before the signal arrives?), provided the setting thread call SetEvent once it's done with its work. The bool is then redundant, which is as it should be.

Win32 事件句柄上的 WaitForSingleObject 允许您伪立即检测所需的信号(取决于进程中的其他线程正在执行的操作),而不进行冗余检查(在信号到达之前您必须执行多少个不必要的循环?) ,前提是设置线程在完成其工作后调用 SetEvent。然后 bool 是多余的,这是应该的。

回答by cmw

Granted this is C#, but I've found this book to be extremely helpful for doing multi-threading development.

当然这是 C#,但我发现这本书对进行多线程开发非常有帮助。

http://www.albahari.com/threading/

http://www.albahari.com/threading/

Some of the info is not language specific.

有些信息不是特定于语言的。