You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++定时器:Start与Stop功能正常,Restart无法终止线程

问题原因分析

问题出在Restart()函数的执行逻辑上:调用Stop()后立刻执行Start(),此时旧线程还没完成退出流程——Stop()只是设置running=false并通知条件变量,但旧线程响应这个信号并退出需要时间,而Start()马上又把running重新设为true,导致旧线程的wait_for条件判断失效,继续执行循环;同时新线程被创建,最终出现多线程同时运行的情况。

单独调用Stop()时,主线程会等待用户输入,这段空档足够旧线程响应退出信号并终止;但Restart()里Stop()和Start()连续执行,没有给旧线程留出退出的时间窗口。

解决方案

方案1:保存线程对象,确保旧线程完全退出后再启动新线程

放弃detach(),改用std::thread对象保存线程实例,在Stop()和Start()中等待旧线程结束,从根本上避免线程失控。

修改后的完整代码:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <chrono>
#include <atomic>

using namespace std;

// 用原子变量保证running的线程安全读写
atomic<bool> running = false;
unsigned int interval = 5000;

condition_variable cv_work;
mutex mu_cv_work;
// 保存线程对象,避免detach导致的线程管理失控
thread worker_thread;

void Start()
{
    unique_lock<std::mutex> lock(mu_cv_work);
    running = true;
    lock.unlock();
    
    // 启动新线程前,确保旧线程已经结束
    if (worker_thread.joinable()) {
        worker_thread.join();
    }
    
    worker_thread = thread([]{
        cout << "new thread" << '\n';
        while (running)
        {
            cout << "work..." << '\n';
            unique_lock<std::mutex> lock(mu_cv_work);
            cout << "sleep" << '\n';
            // 简化条件判断逻辑
            if (cv_work.wait_for(lock, chrono::milliseconds(interval), []{return !running;}))
            {
                cout << "exit thread" << '\n';
                return;
            }
            cout << "done sleeping" << '\n';
        }
    });
}

void Stop()
{
    unique_lock<std::mutex> lock(mu_cv_work);
    running = false;
    lock.unlock();
    cv_work.notify_one();
    
    // 等待线程完全退出
    if (worker_thread.joinable()) {
        worker_thread.join();
    }
}

void Restart()
{
    Stop();
    Start();
}

int main()
{
    Start();
    cout << "press to Stop" << '\n';
    cin.get();
    Stop();                             
    cout << "press to Start" << '\n';
    cin.get();
    Start();
    cout << "press to Restart" << '\n';
    cin.get();
    Restart();                         

    return 0;
}

核心修改点:

  • 用atomic<bool>替代普通bool,消除running变量的线程安全隐患
  • 新增worker_thread变量管理线程实例,避免detach()导致的线程失控
  • 在Stop()和Start()中检查线程可连接状态,等待旧线程完全退出后再执行下一步操作

方案2:临时等待(不推荐)

如果必须保留detach(),可以在Restart()中加入短暂等待,给旧线程留出退出时间,但这种方式依赖硬件性能,可靠性差,仅作为临时 workaround:

void Restart()
{
    Stop();
    this_thread::sleep_for(chrono::milliseconds(100)); // 等待旧线程退出
    Start();
}
验证结果

修改后运行代码,Restart()会先触发旧线程输出exit thread,再创建新线程运行,完全符合期望输出。

内容的提问来源于stack exchange,提问作者poorharambe1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:51:48