{ 1 }CPP_线程管理的基础

一,启动线程

1. 使用C++线程库启动线程,即为构造std::thread对象:

void do_some_work();
std::thread my_thread( do_some_work );

std::thread构造方法

class A
{
public:
  void operator()() const
  {
     std::cout << "hello" << std::endl;
  }
};

A a;
std::thread my_thread(a);

std::thread my_thread(a);调用函数对象a() 传入thread中 ,并把函数对象a 复制到新线程的存储空间中,函数对象的执行和调用都在线程的内存空间中进行。

注意:

  • 如果你传递给thread是一个临时变量,而不是一个已经声明的变量时,会出现C++最令人头痛的语法解析(C++’s most vexing parse),C++编译器解析出的结果将会与你所想的出入很大:
std::thread my_thread( A() );//A()是一个临时的函数对象

这段代码被解析为:
这是一个函数声明,函数名为my_thread。它可以接收一个没有参数的,并且会返回对象A的函数指针。my_thread函数的返回值是std::thread类型。

怎么解决?
使用多组括号,初始化语法 或者 前面代码 都可以避免这个问题:
std::thread my_thread( (A()) );
std::thread my_thread{ A() };

  • 如果不等待线程,必须保证线程结束之前,数据的有效性
struct F
{
  int &i;
  func(int &i_) : i( i _ )  { }

  void operator() ()
  {
    for(unsigned j = 0; j < 100000; ++j)
    {
        std::cout << i << std::endl;
     }
  }
}

void oop()
{
   int number = 0;
   F my_f(unmber);
   std::thread my_f(my_f);
   my_f.detach();
}

由于不等待线程结束, 当oop()执行完成时, 新线程中的函数可能还在运行。 如果线程还在运行, 它就会去调用do_something(i)函数,这时,引用对象 i 已经被销毁了。

二,等待线程完成

如果需要等待线程, std::thread 实例可以使用join()。

class func1{//仿函数对于多线程的运用
public:
    int &a;
    explicit func1(int &a_) : a(a_) {}

    int operator()(int c)
    {
        for(;a < c; ++a)
        {
            cout << a << endl;
        }
        cout << a << endl;
        return a;
    }
};

int main()
{
    int st = 6;
    func1 f(st);

    int c = 10;
    std::thread my_thread (f, c);
    my_thread.join();

    return 0;
}

三,特殊情况下的等待

当倾向在无异常的情况下使用join()时, 需要在异常处理过程中调用join(), 从而避免生命周期的问题。

  • 可以通过使用“资源获取即初始化方式”(RAII, Resource Acquisition Is Initialization)解决此问题。它提供一个类, 在析构函数中使用join():
struct F
{
  int &i;
  func(int &i_) : i( i _ )  { }

  void operator() ()
  {
    for(unsigned j = 0; j < 100000; ++j)
    {
        std::cout << i << std::endl;
     }
  }
}

class G
{
  std::thread& t;

public:
  explicit G(std::thread& t_) : t(t_) {}
  ~G()
  {
    if(t.joinable()) 
    {
      t.join(); 
    }
  } 

  G( G const& )=delete;//不让编译器自动生成,因为这可能会弄丢已经加入的线程。
  G& operator= ( G const& )=delete;
};

struct F;

void oop()
{
  int data = 0;
  F struct_my_f(data);
  std::thread my_t(struct_my_f);
  G my_g(t);
  do_something_in_current_thread();
} 

函数oop() 执行完,对象my_g 也会被销毁, 即使do_something_in_current_thread() 抛出一个异常, 这个销毁依旧会发生。

四,后台运行线程

如果不想等待线程结束, 可以分离(detaching)线程, 从而避免异常安全(exception-safety)问题。 由于使用detach()会让线程在后台运行,如果线程分离, 那么就不可能有 std::thread 对象能引用它, 分离线程的确在后台运行, 所以分离线程不能被加入。

一个可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。

注意:

当在 std::thread 对象中分离线程时,不能对没有执行线程的 std::thread 对象使用detach()。因为和 join()的使用条件相同, 所以可以用同样的方式进行检查,当 std::thread 对象使用 t.detach() 之前,先使用t.joinable()检测该线程是否为可执行线程,如果返回的是true,就可以使用了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容