最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

世界头条:1. 线程管理基础

来源:博客园

线程管理的基础

  • 每个程序至少都有一个线程
  • 各自线程都有自己的入口函数
  • 其他线程和main函数线程同时运行

启动线程

  • 线程在std::thread对象创建时启动

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

  • 除了直接使用函数之外,仿函数也可以作为入口函数


    (资料图片)

    class test{public :void operator()()const{...}}test A;std::thread my_thread(A)

  • 代码中提供的函数对象会复制到新线程的存储空间中,函数对象的副本和原始函数对象保持一直

  • 注意在使用仿函数作为入口的时候,如果传入临时对象会存在语法解析问题,如下

    std::thread my_thread(test())这个时候C++将上述语句解释为返回值为thread,参数为test对象的函数如果需要达到我们入口函数的目的可以参考一下写法std::thread my_thread((test()))std::thread my_thread{test()}

  • lambda表达式也可作为入口函数

    std::thread my_thread([]{...})

  • 启动线程后需要明确是等待线程结束(join())还是让线程自主运行(detach())如果在thread对象结束的时候还没有做出决定,程序就会终止

  • 如果不等待线程,就必须保证在子线程结束之前,可访问的数据一直有效,使用一个能访问局部变量的函数去创建一个线程是一个糟糕的主意

  • 需要在主线程的异常抛出之前调用join()

    struct func;  void f(){    int state = 0;    func my_func(stat);    std::thread t(my_func);    try{      ...;    }    catch(...){      t.join();      throw;    }    t.join();  }
  • 为了确定主线程在结束的时候,能够保证等待使用了局部变量的子线程,可以采用如下方法:

    class thread_guard{    std::thread & t;    public:      explicit thread_guard(std::thread & td):t(td){};      ~thread_guard(){if(t.joinable()){t.join()}};  }  void f(){    int tmp = 0;    std::thread t(my_func,tmp);    thread_guard g(t);  }

    这个时候当tmp走出作用域的时候,t线程对象也会走出作用域,g的析构函数就会自动join() t对象

  • 使用detach()会让线程后台运行,这就意味这主线程不能与之产生直接交互

    void myfun();  std::thread t(myfunc);  t.detach()

参考文献

  • 本文档是我在学习C++并发编程时的笔记,参考书籍《C++并发编程》中文版

关键词: 启动线程 等待线程 结束的时候