C++14下循环std::thread中如何正确使用wait_for实现定时执行与即时退出
你的实现思路方向是正确的,通过条件变量的超时等待机制既可以满足60秒定时执行任务的需求,又能在收到终止请求时立刻唤醒响应,线程绝大多数时间处于休眠状态,不会额外占用CPU资源,符合你的需求。你遇到的运行错误是因为条件变量的使用不符合规范,缺少配套组件。
现有代码的核心问题
- 条件变量必须搭配互斥锁和共享状态标志使用,你当前的代码既没有定义对应的互斥锁,也没有退出校验标志,直接调用
wait_for属于未定义行为,是触发锁错误、std::terminate的直接原因。 wait_for要求传入的std::unique_lock必须处于已锁定状态,你代码中的someLock没有关联任何有效互斥量,也没有加锁逻辑,完全不符合接口调用要求。- 未处理条件变量的虚假唤醒问题:即使没有主动调用
notify_one,wait_for也可能因为系统原因提前返回,此时没有退出标志校验会导致线程异常提前退出。 - 如果你的
std::thread对象在销毁前没有调用join()或者detach(),且线程还处于可联接状态,也会直接触发std::terminate。
符合C++14规范的正确实现
首先定义共享的同步组件:
#include <thread> #include <mutex> #include <condition_variable> #include <chrono> // 同步组件必须配套使用 std::mutex g_mtx; std::condition_variable g_cv; bool g_stop_flag = false;
线程执行函数实现:
void ThreadWork() { std::unique_lock<std::mutex> lock(g_mtx); while (true) { // 等待60秒,或收到退出通知 // 第三个参数为谓词,只有谓词返回true时才会终止等待,天然解决虚假唤醒问题 if (g_cv.wait_for(lock, std::chrono::seconds(60), []{ return g_stop_flag; })) { // 进入此分支说明触发退出标志,直接终止线程 break; } // 超时触发,执行任务,执行前先解锁避免持有锁阻塞退出请求 lock.unlock(); Work(); // 你的业务任务 // 任务执行完成后重新加锁,进入下一轮等待 lock.lock(); } }
终止请求函数实现:
void RequestEnd() { // 修改共享标志必须持有锁 { std::lock_guard<std::mutex> lock(g_mtx); g_stop_flag = true; } // 修改完成后再发通知,保证线程唤醒后一定能读到最新的标志位 g_cv.notify_one(); }
额外注意事项
- 任务执行期间解锁互斥量,可以保证
RequestEnd随时能拿到锁修改退出标志,不会因为任务执行时间长导致终止请求延迟响应。 - 线程启动后,持有
std::thread对象的上下文必须在合适的时机调用join()等待线程退出,避免触发std::terminate。
内容的提问来源于stack exchange,提问作者Thomas B.
相关产品推荐
相关产品推荐

