简体   繁体   English

如何阻止直到满足条件

[英]How to block until a condition is met

I wanted to know what the best way is to block a method until a condition becomes true. 我想知道最好的方法是在条件变为真之前阻塞方法。

Example: 例:

class DoWork
{
  int projects_completed;
  public:
  .....
  void WaitForProjectsCompleted()
  {
   ---->//How do I block until projects_completed == 12;
  }
};

I want it to be used as such 我希望这样使用

class foo
{
 ....
 void someMethod()
 {
    DoWork work;
    work.WaitForProjectsCompleted();//This should block
 }
}

Assuming that there's another thread that's actually going to do something here, an easy thing to use is a std::condition_variable : 假设在这里实际上还有另一个线程将要执行某项操作,则易于使用的是std::condition_variable

std::condition_variable cv;
std::mutex mtx;

void WaitForProjectsCompleted() {
    std::unique_lock<std::mutex> lk(mtx);
    cv.wait(lk, [this]{ 
       return projects_completed >= 12; 
    });
}

Where somewhere else, some other member function might do: 在其他地方,其他一些成员函数可能会执行以下操作:

void CompleteProject() {
    {
        std::lock_guard<std::mutex> lk(mtx);
        ++projects_completed;
    }
    cv.notify_one(); // let the waiter know
}

If projects_completed is atomic, you could instead just spin: 如果projects_completed是atomic,则可以旋转:

void WaitForProjectsCompleted() {
    while (projects_completed < 12) ;
}

That would work fine too. 那也可以。

Condition variables are an excellent synchronization primitive, and in my personal experience it is the tool I respond with to 95% of synchs/threading situations. 条件变量是出色的同步原语,以我个人的经验,它是我对95%的同步/线程情况做出响应的工具。

If you don't have C++11 available you can use boost::condition_variable . 如果没有C ++ 11,则可以使用boost::condition_variable
In which case you won't have the wait version with a predicate (because no lambdas in C++03). 在这种情况下,您将没有带有谓词的wait版本(因为在C ++ 03中没有lambda)。 So you absolutely need to remember to loop over your condition check. 因此,您绝对需要记住遍历条件检查。 As explained in the docs: 如文档中所述:

boost::unique_lock<boost::mutex> lock(mut);
while (projects_completed < 12)
{
    wait(lock);
}

cf: cf:
http://www.boost.org/doc/libs/1_58_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref http://www.boost.org/doc/libs/1_58_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref

That's because you get no guarantee that the condition is fulfilled after a notification, particularly because the lock can be acquired by another thread in the interstice between unlock and notify. 那是因为您无法保证在通知后条件会得到满足,尤其是因为锁可以由解锁和通知之间的另一个线程获取。 Also a spurious wake up could happen. 也可能会发生虚假的唤醒。

I also wrote an article about it: 我也写了一篇关于它的文章:
http://www.gamedev.net/page/resources/_/technical/general-programming/multithreading-r3048 http://www.gamedev.net/page/resources/_/technical/general-programming/multithreading-r3048

Also if you use timed_wait (and I recommend it as it often mitigates priority inversion ), another trap not to fall into is the timeout, because of the loop you cannot use a relative timeout (like 2 seconds) you need an absolute system time determined before entering the loop. 另外,如果您使用timed_wait (并且我建议使用它,因为它通常可以减轻优先级反转 ),那么另一个不容易陷入的陷阱就是超时,因为循环无法使用相对超时(例如2秒),因此需要确定绝对系统时间在进入循环之前。
boost makes it very clean with this technique: 使用此技术, boost使其非常干净:

system_time const timeout = get_system_time() + posix_time::seconds(2);

About the spin lock pattern proposed by Barry, I would not recommend it, unless you are in a real time environment, like playstation 3/4 or equivalent. 关于Barry提出的旋转锁定模式,除非您处于实时环境(例如playstation 3/4或同等水平)中,否则我不建议您这样做。 Or unless you are sure it won't last for more than a few seconds. 或者,除非您确定它不会持续超过几秒钟。
By using spin locking you waste power, and you don't leave chance for CPU to enter sleep states (cf intel speed step). 通过使用自旋锁定,您会浪费电源,并且不会留给CPU进入睡眠状态的机会(参见英特尔速度步长)。
This also has consequences on fairness and scheduling, as explained on wikipedia: 如Wikipedia所述,这也会对公平性和日程安排产生影响:
https://en.wikipedia.org/wiki/Spinlock https://zh.wikipedia.org/wiki/自旋锁

Finally if you don't have boost, since windows Vista we get natives Win32 functions: 最后,如果您没有增强功能,从Windows Vista开始,我们将获得本机Win32函数:
SleepConditionVariableCS
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686301(v=vs.85).aspx https://msdn.microsoft.com/zh-CN/library/windows/desktop/ms686301(v=vs.85).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 循环直到满足特定条件 - loop until a certain condition is met 在满足某些条件之前,如何继续将 Halide 管道的输出传递回管道? - How do I keep passing the output of a Halide pipeline back into the pipeline until some condition is met? 如何制作一个 C++ 宏来检查条件,如果不满足则打印错误并执行用户块? - How to make a C++ macro which checks condition, prints error if not met and executes user block? 不断询问用户输入直到满足条件 C++ - Keep asking for user input until condition met C++ 需要帮助创建一个睡眠状态的循环,当条件满足时它会停止直到下一个动作 - Need help creating a Loop which sleeps a condition, when condition is met it stops until the next action 满足条件时如何在日食中停止执行 - how to stop exection in eclipse when a condition is met 如果不满足条件,如何无限期地重做一个动作? - How to redo an action indefinitely if condition is not met? 满足条件时如何取消std :: async? - How to cancel std::async when condition is met? 如果不满足循环条件,如何执行一段代码? - How to execute a piece of code if the condition of a loop is not met? 满足特定条件时如何限制对象创建 - How to restrict object creation when certain condition is met
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM