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

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

线程重启时无法终止旧线程的问题解决

问题核心在于:Restart()中调用Stop()后立刻执行Start(),此时旧线程还未完成退出逻辑,Start()就将running重新设为true,导致旧线程的wait_for条件检查失败,继续执行循环;同时新线程被创建,最终出现多线程并行运行的情况。而单独调用Stop()时,主线程会等待用户输入,这段时间足够旧线程响应通知并退出。

修复后的代码示例

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

using namespace std;

atomic<bool> running = false; // 改用atomic保证线程安全读写
unsigned int interval = 5000;

condition_variable cv_work;
mutex mu_cv_work;
thread worker_thread; // 保存线程对象,避免detach丢失线程控制权

void Start()
{
    unique_lock<std::mutex> lock(mu_cv_work);
    if (running || worker_thread.joinable()) {
        return; // 避免重复启动线程
    }
    running = true;
    lock.unlock();
    
    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(); // 阻塞等待旧线程完全退出
        worker_thread = thread(); // 重置线程对象,确保下次启动正常
    }
}

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;
}

关键修改说明

  1. 原子变量存储运行状态:用atomic<bool>替代普通bool,确保多线程对running的读写操作无数据竞争。
  2. 保留线程对象控制权:不再使用detach(),而是用全局thread对象保存工作线程,通过join()等待线程完全退出。
  3. 避免重复启动:Start()中增加检查逻辑,防止已有线程运行时重复创建新线程。
  4. 等待线程退出再继续:Stop()中调用join()阻塞主线程,确保旧线程彻底终止后才返回,让Restart()中的Start()能安全创建新线程。

预期输出

press to Stop
new thread
work...
sleep
                      // KEY PRESS
exit thread
press to Start
                      // KEY PRESS
new thread
work...
sleep
press to Restart
                      // KEY PRESS    
exit thread             
new thread
work...
sleep
done sleeping
work...
sleep

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:24:52