C++周期性定时器实现:线程安全停止问题求助
C++线程安全定时器实现方案
针对你遇到的定时器停止阻塞、线程安全问题,以下是修正后的完整实现及关键说明:
核心问题分析
- 非线程安全的状态变量:原
Activated是普通bool,多线程读写会触发未定义行为(编译器可能优化读取,导致线程无法感知状态变化)。 - 阻塞式线程管理:原
scheduler若直接调用thread::join会卡死主线程,无法触发后续停止操作。 - 无法及时响应停止信号:单纯用
sleep_for会让定时器线程在等待周期内无法感知停止指令,必须等待周期结束才能退出。
修正后的定时器类实现
#pragma once #ifndef __MyTimer_h__ #define __MyTimer_h__ #include <thread> #include <mutex> #include <condition_variable> #include <chrono> #include <functional> template <typename Cback> class MyTimer { public: MyTimer() = delete; MyTimer(Cback cb, int secs); ~MyTimer(); // 禁用拷贝(线程不可拷贝) MyTimer(const MyTimer&) = delete; MyTimer& operator=(const MyTimer&) = delete; void start(); // 启动定时器线程 void stop(); // 安全停止定时器 private: void timer_loop(); // 定时器线程核心循环 bool activated_; Cback callback_; int duration_secs_; std::thread timer_thread_; std::mutex mtx_; std::condition_variable cv_; }; template <typename Cback> MyTimer<Cback>::MyTimer(Cback cb, int secs) : callback_(std::move(cb)), duration_secs_(secs), activated_(false) {} template <typename Cback> MyTimer<Cback>::~MyTimer() { stop(); // 析构时自动停止线程,避免资源泄漏 } template <typename Cback> void MyTimer<Cback>::start() { std::lock_guard<std::mutex> lock(mtx_); if (!activated_ && !timer_thread_.joinable()) { activated_ = true; timer_thread_ = std::thread(&MyTimer::timer_loop, this); } } template <typename Cback> void MyTimer<Cback>::stop() { { std::lock_guard<std::mutex> lock(mtx_); if (!activated_) return; activated_ = false; } cv_.notify_one(); // 唤醒等待中的定时器线程 if (timer_thread_.joinable()) { timer_thread_.join(); // 等待线程安全退出 } } template <typename Cback> void MyTimer<Cback>::timer_loop() { std::unique_lock<std::mutex> lock(mtx_); while (activated_) { // 临时解锁,避免回调执行时持有锁影响stop响应 lock.unlock(); callback_(); lock.lock(); // 等待周期或被stop唤醒,避免无意义的阻塞 cv_.wait_for(lock, std::chrono::seconds(duration_secs_), [this]() { return !activated_; }); } } #endif
修正后的主函数
#include <iostream> #include <memory> #include <chrono> #include <iomanip> void printcurrenttime() { auto now = std::chrono::system_clock::now(); std::time_t now_time = std::chrono::system_clock::to_time_t(now); std::cout << " " << std::ctime(&now_time); } void callbackfunc() { std::cout << "callback function called at"; printcurrenttime(); } int main() { std::cout << "\nmain function called at"; printcurrenttime(); std::unique_ptr<MyTimer<std::function<void(void)>>> timer( new MyTimer<std::function<void(void)>>(callbackfunc, 2)); timer->start(); // 启动定时器,主线程继续执行 std::this_thread::sleep_for(std::chrono::seconds(20)); std::cout << "\nStopping timer...\n"; timer->stop(); // 安全停止定时器 std::cout << "\nMain thread exiting\n"; return 0; }
关键实现细节
- 线程安全状态控制:用
std::mutex保护activated_变量,确保主线程和定时器线程的读写操作互斥,避免数据竞争。 - 即时停止响应:用
std::condition_variable::wait_for替代单纯的sleep_for,调用stop()时会立即唤醒定时器线程,无需等待剩余周期。 - 非阻塞启动:
start()仅启动线程就返回,主线程可正常执行后续逻辑,直到需要停止时调用stop()等待线程退出。 - 安全析构:析构函数自动调用
stop(),确保对象销毁时线程已完全退出,防止悬空线程。
内容的提问来源于stack exchange,提问作者Tej Ravi
相关产品推荐
相关产品推荐

