不考虑线程间的竞争的话,对于启动线程,需要考虑到启动线程后是要对线程进行join还是detach,同时也需要注意进行操作的时间,确保要在线程对象销毁前。
如果选择进行join,那么如果发生异常该怎么办?
如果detach了那么如果存在子线程使用了已经释放的资源吗?
学会使用类似于lock_guard的RAII(资源获取即初始化)的方式来对线程进行管理,使用局部变量控制线程的join。
如果要在创建线程时候传递参数,那么需要注意的还包括自己传递的参数是什么性质的,是引用传递,还是复制拷贝?理解thread类构造时候的语义才不会对莫名其妙的结果摸不着头脑。
构建一个线程对象是包含多种方法的,可以直接传入函数构建,也可以通过与类结合、或者使用lambda表达式。
线程是可移动(movable)而非可复制的(copyable)。
thread t1(do_something);
thread t2 = std::move(t1);
Detach
在thread线程上调用detach,会把线程丢在后台运行,也没有直接的方法与之通信。也不再可能等待该线程完成。分离的线程的所有权和控制权被转交给C++运行时库,以确保与线程相关联的资源在线程退出后能被正确回收。
分离线程是存在风险的,如果子线程操作着主线程的指针或者其他数据。现在子线程分离了,同时如果主线程先于子线程结束,此时子线程还在继续跑啊跑啊,刷着副本,然后就会使用到已经释放的空间那么就会如下了--
thread_guard
// 使用RAII方式管理thread的正常或者发生异常时候能正确join
class thread_guard
{
public:
explicit thread_guard(thread &trd) : trdRef(trd)
{}
// 该类析构时候自动执行thread的join,即使线程执行过程中出现异常也一样
~thread_guard()
{
if (trdRef.joinable())
{
trdRef.join();
}
}
thread_guard(thread_guard const &) = delete;
thread_guard &operator= (thread_guard const &) = delete;
private:
thread &trdRef;
};