zoukankan      html  css  js  c++  java
  • std::get<C++11多线程库>(03): 子线程的完整性

     1 #include <QCoreApplication>
     2 #include <iostream>
     3 #include <thread>
     4 
     5 /*
     6  *  话题:一定要保证新线程结束之前,访问到的数据变量具有有效性。否则会产生未定义的行为和异常。
     7  *      单线程代码中,对象销毁之后再去访问,也会产生未定义行为——不过,线程的生命周期增加了这个问题发生的几率。
     8  *
     9  * 场景1: 线程函数访问的局变量已销毁。
    10  *        初始线程的函数已执行完毕,但新线程中使用了 初始函数中局部变量的指针或引用。 这种情况下, 新线程继续访问将导致未定行为。
    11  *
    12  *
    13  * 场景2:新线程使用一个可调用对象作为线程函数,新线程结束前,可调用对象被销毁。
    14  *       可调用对象会被复制一份到新线程的内存空间, 如果可调用对象中包含指针或者引用,在原可调用对象被析构后,
    15  *        复制到新线程中的副本可调用对象继续使用指针或者引用,将是未定义的。
    16  *
    17  *
    18  * 处理这种情况的常规方法:
    19  *        使线程函数的功能齐全,将数据复制到线程中,而非复制到共享数据中。
    20  *        如果使用一个可调用的对象作为线程函数,这个对象就会复制到线程中,而后原始对象就会立即销毁。但对于对象中包含的指针和引用还需谨慎。
    21  *        使用一个能访问局部变量的函数去创建线程是一个糟糕的主意(除非十分确定线程会在函数完成前结束)。
    22  *
    23  * 此外,可以通过join()函数来确保线程在函数完成前结束。
    24 */
    25 struct Obj{
    26     Obj(int& i):_i(i){}
    27     void operator()(){
    28         for (; _i>0; --_i)   //潜在访问隐患:悬空引用
    29             std::cout<<"i = "<<_i<<std::endl;
    30     }
    31 
    32 private:
    33     int& _i;
    34 };
    35 int main(int argc, char *argv[])
    36 {
    37     QCoreApplication a(argc, argv);
    38 
    39     int x = 10000; //局变量
    40     Obj obj(x);
    41     std::thread t(obj);
    42     //t.join();  //加入式。 等待 新线程的结束,访问变量 x 的引用 _i 不会出问题
    43     t.detach();  //分离式。 不等待 新线程的结束, 访问变量 x 的引用 _i 可能会出问题
    44 
    45     return a.exec();
    46 }
  • 相关阅读:
    NewtonSoft.Json
    属性
    csv文件
    C#和递归算法实现删除,清空,拷贝目录
    朴素贝叶斯应用:垃圾邮件分类
    压缩图片
    numpy分布图
    鸢尾花
    numpy数组及处理:效率对比
    完整的中英文词频统计
  • 原文地址:https://www.cnblogs.com/azbane/p/15334378.html
Copyright © 2011-2022 走看看