多线程workerClass数据独立存储及跨类全局vector检索需求
多线程核心独立数据存储实现方案
首先得明确你的核心诉求:每个线程对应一个CPU核心,各自维护独立的id、packetCount和packetDropped属性,通过全局的std::vector<workerClass>来统一存储这些实例,方便后续在其他类中检索数据。下面是具体的实现思路和代码示例:
1. 调整workerClass类结构
首先要把run函数设为public(线程需要调用它),同时确保原子变量的初始化逻辑清晰:
#include <atomic> #include <vector> #include <thread> #include <iostream> #include <chrono> class workerClass { private: std::atomic<int> id; std::atomic<int> packetCount; std::atomic<int> packetDropped; // 可选:添加停止标志,优雅终止线程 std::atomic<bool> stopFlag{false}; public: // 构造函数初始化原子变量 workerClass() : id(-1), packetCount(0), packetDropped(0) {} // 线程执行的核心函数 void run(int threadId) { id.store(threadId, std::memory_order_relaxed); // 这里模拟线程的业务逻辑:处理数据包,更新计数 while (!stopFlag.load(std::memory_order_relaxed)) { // 示例:每处理10个数据包模拟丢1个 packetCount.fetch_add(1, std::memory_order_relaxed); if (packetCount.load(std::memory_order_relaxed) % 10 == 0) { packetDropped.fetch_add(1, std::memory_order_relaxed); } // 实际业务中替换为真实数据包处理逻辑 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } // 优雅停止线程的接口 void stop() { stopFlag.store(true, std::memory_order_relaxed); } // 提供获取数据的接口,供其他类检索 int getId() const { return id.load(std::memory_order_relaxed); } int getPacketCount() const { return packetCount.load(std::memory_order_relaxed); } int getPacketDropped() const { return packetDropped.load(std::memory_order_relaxed); } };
2. 全局vector的初始化与线程创建
全局vector需要在程序启动时根据CPU核心数初始化,然后为每个核心创建对应的线程:
// 全局存储每个核心对应的worker实例 std::vector<workerClass> workers; // 存储线程对象,方便管理与回收 std::vector<std::thread> threads; void initWorkers() { // 获取当前系统的CPU核心数 size_t coreCount = std::thread::hardware_concurrency(); if (coreCount == 0) { coreCount = 4; // fallback值,防止获取核心数失败 } workers.resize(coreCount); // 为每个核心创建线程,绑定对应的worker的run函数 for (size_t i = 0; i < coreCount; ++i) { threads.emplace_back(&workerClass::run, &workers[i], static_cast<int>(i)); } } // 程序退出时回收线程资源 void cleanupWorkers() { // 先通知所有线程停止 for (auto& worker : workers) { worker.stop(); } // 等待所有线程执行完毕 for (auto& thread : threads) { if (thread.joinable()) { thread.join(); } } }
3. 在其他类中检索数据
后续可以在任意类中直接访问全局的workers vector,通过索引或者遍历获取每个核心的统计数据:
class DataRetriever { public: void printWorkerStats() { std::cout << "=== 各核心线程统计数据 ===" << std::endl; for (const auto& worker : workers) { std::cout << "核心ID: " << worker.getId() << " | 处理数据包总数: " << worker.getPacketCount() << " | 丢包数: " << worker.getPacketDropped() << std::endl; } } };
4. 关键注意事项
- 原子变量内存序:这里用
std::memory_order_relaxed足够,因为我们只需要保证变量读写的原子性,不需要严格的内存同步。 - 线程安全:如果只是检索数据(只读操作),无需额外加锁;如果有修改worker实例的操作,需要配合
std::mutex保证线程安全。 - 资源回收:一定要在程序退出时调用
cleanupWorkers(),避免线程资源泄漏。
内容的提问来源于stack exchange,提问作者Vinay Shukla
相关产品推荐
相关产品推荐

