c++ - 正确使用 std::condition_variable 来触发定时执行

标签 c++ multithreading c++11 condition-variable

我正在尝试以固定的时间间隔执行一段代码。我有一些基于裸 pthread 的东西,现在我想使用 std::thread 做同样的事情。

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

bool running;
std::mutex mutex;
std::condition_variable cond;

void timer(){
  while(running) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    std::lock_guard<std::mutex> guard(mutex);
    cond.notify_one();
  }
  cond.notify_one();
}

void worker(){
  while(running){
    std::unique_lock<std::mutex> mlock(mutex);
    cond.wait(mlock);
    std::cout << "Hello World" << std::endl;
    //... do something that takes a variable amount of time ...//
  }
}

int main(){
  running = true;
  auto t_work = std::thread(worker);
  auto t_time = std::thread(timer);
  std::this_thread::sleep_for(std::chrono::milliseconds(10000));

  running = false;
  t_time.join();
  t_work.join();
}

实际上,worker 所做的事情需要不同的时间,但应该以固定的时间间隔进行安排。它似乎有效,但我对此还很陌生,所以有些事情我不清楚......

  • 为什么我需要一个互斥体?我并没有真正使用条件,但是每当计时器发送信号时,工作线程就应该执行其工作。

  • timer真的需要在循环后再次调用cond.notify_one()吗?这是取自旧代码,iirc 的原因是为了防止 worker 永远等待,以防 timerworker 完成时完成。还在等待。

  • 我需要 running 标志吗?还是有更好的方法来break 跳出循环?

PS:我知道还有其他方法可以确保固定的时间间隔,并且我知道我当前的方法存在一些问题(例如,如果 worker 需要的时间比使用的时间间隔更多) 计时器)。但是,我想先了解那段代码,然后再对其进行太多更改。

最佳答案

Why do I need a mutex at all? I do not really use a condition, but whenever the timer sends a signal, the worker should do its job.

您需要互斥体的原因是等待条件满足的线程可能会受到虚假唤醒。为了确保您的线程确实收到了条件正确满足的通知,您需要检查这一点,并且应该在 wait 调用中使用 lambda 来执行此操作。为了保证在虚假唤醒之后但在检查变量之前该变量不会被修改,您需要获取一个互斥体,以便您的线程是唯一可以修改条件的线程。在您的情况下,这意味着您需要为工作线程添加一种方法来实际验证计时器是否已用完。

Does the timer really need to call cond.notify_one() again after the loop? This was taken from the older code and iirc the reasoning is to prevent the worker to wait forever, in case the timer finishes while the worker is still waiting.

如果在循环后不调用notify,工作线程将无限期等待。因此,要干净地退出程序,您实际上应该调用notify_all()以确保每个等待条件变量的线程都被唤醒并可以干净地终止。

Do I need the running flag, or is there a nicer way to break out of the loops?

运行标志是完成您想要的事情的最干净的方式。

关于c++ - 正确使用 std::condition_variable 来触发定时执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43495020/

相关文章:

c++ - std::vector 的 std::functions 查找

c++ - 引用变量是否在堆栈中占用内存?

c++ - 如何禁用编辑控件对对话框首次启动的关注?

带有 vector 的 C++ IF 评估操作数

java - 如何使用java在多线程中使用log4j?

java - 在 Java 中使用线程时是否需要替代 runnable

c++ - 为什么没有 std::stou?

c++ - QTextDocument:如何从缓存中删除资源

c++ - STL列表-[intNumber]的作用是什么?

iphone - PerformSelector In后台泄漏在设备上