C++中如何在线程外获取atomic原子变量的值并触发对应业务逻辑
解决方案
代码优化核心要点
- 给后台循环增加合理休眠,避免死循环占满CPU核心,休眠时长可设为100ms,远小于3秒的超时阈值,不会影响状态判断精度
- 增加历史状态缓存,仅当状态实际发生变更时才调用
prepareData(),减少无效调用开销 - 原子变量使用标准
load()/store()方法访问,保证跨线程操作的可见性和安全性 - 修正原代码中变量名不一致的问题:头文件定义的是
STATUS,后台线程中错误写为MC_COMPUTER_STATUS,统一变量命名 - 头文件中不要直接定义全局原子变量,改为
extern声明,放到cpp文件中定义,避免多文件引用时出现重复定义错误
修正后代码
ProtoApiManager.hpp
#include <atomic> #include <chrono> using namespace std::chrono; // 状态变量声明 extern std::atomic_int STATUS; // 超时常量统一管理 constexpr int NAV_COMMS_TIMEOUT_MS = 3000;
ProtoApiManager.cpp
#include "ProtoApiManager.hpp" // 原子变量定义 std::atomic_int STATUS = ATOMIC_VAR_INIT(0); void ProtoApiManager::startBgThread() { _keep_running = true; // 初始化上次接收数据的时间 _last_status_msg_rx = MiscUtils::getTimeNow(); _t_bg_tasks = std::thread(&ProtoApiManager::onThreadBgTasks, this); } void ProtoApiManager::onThreadBgTasks() { // 缓存上一次的状态,避免重复触发prepareData int last_status = STATUS.load(std::memory_order_relaxed); do { milliseconds currentTime = MiscUtils::getTimeNow(); auto delta = currentTime - _last_status_msg_rx; int new_status = delta.count() > NAV_COMMS_TIMEOUT_MS ? 0 : 1; // 仅状态变化时更新并触发数据组装 if (new_status != last_status) { STATUS.store(new_status, std::memory_order_relaxed); if (new_status == 0) { std::cout << "Time out OFFLINE" << std::endl; } else { std::cout << "Time out ONLINE" << std::endl; } prepareData(); last_status = new_status; } // 休眠降低CPU占用 std::this_thread::sleep_for(milliseconds(100)); } while (_keep_running); } // UDP数据接收回调逻辑补充:每次收到合法数据时更新接收时间 void ProtoApiManager::onUdpDataReceived() { _last_status_msg_rx = MiscUtils::getTimeNow(); }
ProtoApiManager.process.cpp
#include "ProtoApiManager.hpp" void ProtoApiManager::prepareData() { // 组装数据 hardwareItemStatusMCComputer->set_hardwaretype(10); hardwareItemStatusMCComputer->set_hardwarename("MC Computer"); // 读取原子变量最新值 hardwareItemStatusMCComputer->set_hardwarestatus(STATUS.load(std::memory_order_relaxed)); // UDP发送逻辑 }
额外注意事项
- 如果
prepareData()涉及非线程安全的资源操作,需要加互斥锁保护,或者把调用逻辑投递到指定的单线程执行 - 程序退出时要主动将
_keep_running设为false,并调用后台线程的join()方法回收资源,避免崩溃
内容的提问来源于stack exchange,提问作者Sara
相关产品推荐
相关产品推荐

