当前位置: 首页 > news >正文

C++编程指南20 - 使用 joining_thread以确保线程不会在变量生命周期之外运行

一:概述

        在多线程编程中,如果一个线程需要访问外部作用域的变量,就必须保证这个变量在 线程结束之前依然有效,否则可能会出现 悬空指针(dangling pointer) 的问题,导致 未定义行为。

二:如何解决?

        使用 joining_thread(类似 std::thread,但会在析构时自动 join(),且不能 detach())可以避免这种问题,因为:

  • 线程的生命周期受到管理:不会意外地 detach() 导致资源泄漏。
  • 作用域内对象的生命周期受控:确保线程所访问的对象在其执行期间是有效的。

三:代码示例

#include <iostream>
#include <thread>
#include <memory>

void f(int* p) {
    *p = 99;
}

int glob = 33;

void some_fct(int* p) {
    int x = 77;
    std::thread t0(f, &x);         // ✅ OK:x 在作用域内
    std::thread t1(f, p);          // ✅ OK:p 是外部传入的
    std::thread t2(f, &glob);      // ✅ OK:glob 是全局变量
    auto q = std::make_unique<int>(99);
    std::thread t3(f, q.get());    // ❌ 错误!q 是局部变量,t3 可能在 q 析构后访问无效地址
    t0.join();
    t1.join();
    t2.join();
    t3.join();
}

         以上 t3(f, q.get()); 可能会导致 悬空指针,因为 qsome_fct() 结束时会被销毁,而 t3 可能仍然在运行,这样 f() 就可能访问已释放的内存,导致 未定义行为。

        解决办法:使用 joining_thread(概念类似 std::thread,但会在析构时自动 join(),确保线程不会在变量生命周期之外运行)

#include <iostream>
#include <thread>
#include <memory>

class joining_thread {
    std::thread t;
public:
    template <typename... Args>
    explicit joining_thread(Args&&... args) : t(std::forward<Args>(args)...) {}

    ~joining_thread() {
        if (t.joinable()) {
            t.join();
        }
    }

    joining_thread(const joining_thread&) = delete;
    joining_thread& operator=(const joining_thread&) = delete;
};

void f(int* p) {
    *p = 99;
}

int glob = 33;

void some_fct(int* p) {
    int x = 77;
    joining_thread t0(f, &x);          // ✅ OK:x 在作用域内
    joining_thread t1(f, p);           // ✅ OK:p 是外部传入的
    joining_thread t2(f, &glob);       // ✅ OK:glob 是全局变量
    auto q = std::make_unique<int>(99);
    joining_thread t3(f, q.get());     // ✅ OK:q 仍然在作用域内

    // 这里不需要手动 join(),析构时会自动 join()
}
 

相关文章:

  • 20250302让chrome打开刚关闭的网页
  • 计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型音乐推荐系统 音乐数据分析 音乐可视化 音乐爬虫 知识图谱 大数据毕业设计
  • 基因枷锁下的太空梦 —— 千钧一发电影观后感
  • 《HarmonyOS Next × ArkTS框架:从AI模型压缩到智能家居控制的端侧开发指南》
  • 算法--贪心
  • 基于SpringBoot + Vue的商城购物系统实战
  • 非平稳时间序列分析(二)——ARIMA(p, d, q)模型
  • unity大坐标抖动处理测试
  • UNIAPP前端配合thinkphp5后端通过高德API获取当前城市天气预报
  • TCP和UDP比较
  • 使用mybatis plus的@Select自定义sql时,如何实现通用的分页查询?
  • MacDroid for Mac v2.3 安卓手机文件传输助手 支持M、Intel芯片 4.7K
  • 物联网坡体斜度监测设备 顶级功能,还想集成CPS 红外 土质监测
  • Hue 编译异常:ImportError: cannot import name ‘six‘ from ‘urllib3.packages‘
  • 数据挖掘工程师的技术图谱和学习路径
  • 1004. 最大连续1的个数 III
  • 为你详细介绍系统数据库的概念结构、逻辑结构、物理结构设计方法,以及数据库的物理独立性的相关内容:
  • DeepSeek-R1 本地部署及Api调用
  • 动态规划刷题
  • 人工智能AI在汽车设计领域的应用探索
  • 优秀网站设计分析/公司软文
  • WordPress客服插件破解版/端点seo博客
  • 网站如何有排名靠前/2345网址中国最好
  • 长沙搜索排名优化公司/seo营销优化软件
  • 智邦国际erp系统登录/网站性能优化的方法有哪些
  • 美食 网站模板/优化设计答案