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

T.T*_*.T. 9 c c++ windows resources winapi

对于多线程程序,我想做类似下面的事情:

// wait for variable to become true but don't hog resources  
// then re-sync queues  
Run Code Online (Sandbox Code Playgroud)

就是这样的一个很好的解决方案?

while (!ready) {
    Thread.Sleep(250); // pause for 1/4 second;
};
Run Code Online (Sandbox Code Playgroud)

Nik*_*sov 15

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

  • 请注意,条件变量是Vista的新增功能,以防与XP的兼容性很重要. (2认同)
  • Boost带有一个非常好的条件变量实现,它也适用于旧版本的Windows. (2认同)

And*_*dky 5

尝试使用事件(内核对象)而不是简单变量,并将循环替换为:

WaitForSingleObject(hEventHandle, INFINITE);
Run Code Online (Sandbox Code Playgroud)


Emi*_*ier 5

以下是使用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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 我知道这是可能的 - 请参阅我对我的回答的评论 - 但是,除非您试图揭示除了对容易出错的C和Microsoft锁定Windows API的盲目奉献之外的其他事情,否则请点击1.令我感到困惑的是为什么人们会回答那些没有挑战的答案,但是,我猜这里的人数很少. (2认同)
  • 值得注意的是,这里演示的所有增强功能都被接受到了`std`lib中,因此现在已经完全成为标准,使得它们甚至比专有的做同样事情的方式更优越. (2认同)