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

C++多线程中如何用std::shared_ptr等实现get函数结果复用?

使用std::shared_ptr、std::future、std::async实现多任务共享耗时函数结果

完全可以用这些工具实现你的需求,核心思路是用原子化的std::shared_ptr包裹std::future,确保只有第一个任务触发耗时的get()函数调用,后续所有任务共享同一个future的结果——要么直接读取已就绪的数据,要么阻塞等待数据准备完成。

设计核心要点

  1. 替换全局变量:把原全局Objs.text替换为一个原子共享指针:std::atomic<std::shared_ptr<std::future<数据类型>>> g_future_ptr;(数据类型根据get()返回值调整,示例中用std::string)。
  2. 任务逻辑:每个任务的check()方法中:
    • 原子加载当前的g_future_ptr,判断是否为空;
    • 若为空,用std::async(std::launch::async, &get)启动异步任务,将返回的future存入新的shared_ptr,再通过原子交换操作更新全局指针(避免多线程竞态创建重复任务);
    • 若不为空,直接复用已有的future;
    • 调用future->get()等待结果就绪,所有任务将拿到同一个结果,无需重复调用get()。

完整代码示例

#include <iostream>
#include <future>
#include <memory>
#include <atomic>
#include <thread>
#include <chrono>

// 模拟耗时的get函数
std::string get() {
    std::cout << "正在执行耗时的get函数...\n";
    std::this_thread::sleep_for(std::chrono::seconds(3)); // 模拟耗时操作
    return "从get函数获取的数据";
}

// 全局原子共享指针,存储future
std::atomic<std::shared_ptr<std::future<std::string>>> g_future_ptr;

// 任务类
class Task {
public:
    void check() {
        // 原子加载当前future指针
        auto future_ptr = g_future_ptr.load();
        
        // 若指针为空,尝试创建新的异步任务
        if (!future_ptr) {
            auto new_future = std::make_shared<std::future<std::string>>(
                std::async(std::launch::async, &get)
            );
            // 原子交换:只有当前指针仍为空时才替换,避免多线程重复创建任务
            if (g_future_ptr.compare_exchange_weak(future_ptr, new_future)) {
                std::cout << "任务" << std::this_thread::get_id() << "触发了get函数\n";
            } else {
                // 交换失败,说明其他线程已创建任务,复用已有指针
                future_ptr = g_future_ptr.load();
            }
        }
        
        // 等待结果并获取
        std::string result = future_ptr->get();
        std::cout << "任务" << std::this_thread::get_id() << "获取到结果:" << result << "\n";
        // 可将result写入Objs或直接使用
        // Objs.text = result;
    }
};

int main() {
    Task t1, t2, t3, t4;
    
    // 启动多个任务线程
    std::thread th1(&Task::check, &t1);
    std::thread th2(&Task::check, &t2);
    std::thread th3(&Task::check, &t3);
    
    // 延迟启动第四个任务,模拟后续加入的任务
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::thread th4(&Task::check, &t4);
    
    th1.join();
    th2.join();
    th3.join();
    th4.join();
    
    return 0;
}

关键细节说明

  • 原子操作保护:std::atomic<std::shared_ptr<...>>和compare_exchange_weak确保全局指针的读写是线程安全的,避免多个线程同时创建get()任务的竞态条件;
  • 强制异步执行:用std::launch::async参数确保std::async创建独立线程执行get(),避免默认策略下可能的同步执行;
  • 结果复用:future->get()第一次调用会阻塞至get()完成,后续调用直接返回已就绪的结果,不会重复执行耗时操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:18:16