c++中关于std::thread的join的思考

std::thread是c++11新引入的线程标准库,通过其可以方便的编写与平台无关的多线程程序,虽然对比针对平台来定制化多线程库会使性能达到最大,但是会丧失了可移植性,这样对比其他的高级语言,可谓是一个不足。终于在c++11承认多线程的标准,可谓可喜可贺!!!

在使用std::thread的时候,对创建的线程有两种操作:等待/分离,也就是join/detach操作。join()操作是在std::thread t(func)后“某个”合适的地方调用,其作用是回收对应创建的线程的资源,避免造成资源的泄露。detach()操作是在std::thread t(func)后马上调用,用于把被创建的线程与做创建动作的线程分离,分离的线程变为后台线程,其后,创建的线程的“死活”就与其做创建动作的线程无关,它的资源会被init进程回收。

在这里主要对join做深入的理解。

由于join是等待被创建线程的结束,并回收它的资源。因此,join的调用位置就比较关键。比如,以下的调用位置都是错误的。

例子一:

void test()
{
} bool do_other_things()
{
} int main()
{
std::thread t(test);
int ret = do_other_things();
if(ret == ERROR) {
return -1;
} t.join();
return 0;
}

很明显,如果do_other_things()函数调用返ERROR, 那么就会直接退出main函数,此时join就不会被调用,所以线程t的资源没有被回收,造成了资源泄露。

例子二:

void test()
{
} bool do_other_things()
{
} int main()
{
std::thread t(test); try {
do_other_things();
}
catch(...) {
throw;
}
t.join();
return 0;
}

这个例子和例子一差不多,如果调用do_other_things()函数抛出异常,那么就会直接终止程序,join也不会被调用,造成了资源没被回收。

那么直接在异常捕捉catch代码块里调用join就ok啦。

例子三:

void test()
{
} bool do_other_things()
{
} int main()
{
std::thread t(test); try {
do_other_things();
}
catch(...) {
t.join();
throw;
}
t.join();
return 0;
}

是不是很多人这样操作?这样做不是万无一失的, try/catch块只能够捕捉轻量级的异常错误,在这里如果在调用do_other_things()时发生严重的异常错误,那么catch不会被触发捕捉异常,同时造成程序直接从函数调用栈回溯返回,也不会调用到join,也会造成线程资源没被回收,资源泄露。

所以在这里有一个方法是使用创建局部对象,利用函数调用栈的特性,确保对象被销毁时触发析构函数的方法来确保在主线程结束前调用join(),等待回收创建的线程的资源。

class mythread {
private:
std::thread &m_t; public:
explicit mythread(std::thread &t):m_t(t){}
~mythread() {
if(t.joinable()) {
t.join()
}
} mythread(mythread const&) = delete;
mythread& operate=(mythread const&) = delete;
} void test()
{
} bool do_other_things()
{
} int main()
{
std::thread t(test);
mythread q(t); if(do_other_things()) {
return -1;
} return 0;
}

在上面的例子中,无论在调用do_other_things()是发生错误,造成return main函数,还是产生异常,由于函数调用栈的关系,总会回溯的调用局部对象q的析构函数,同时在q的析构函数里面先判断j.joinable()是因为join操作对于同一个线程只能调用一次,不然会出现错误的。这样,就可以确保线程一定会在主函数结束前被等待回收了。

c++11中关于std::thread的join的思考的更多相关文章

  1. c++11中关于`std::thread`线程传参的思考

    关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...

  2. C++11并发之std::thread<转>

    最近技术上没什么大的收获,也是悲催的路过~ 搞一点新东西压压惊吧! C++11并发之std::thread 知识链接: C++11 并发之std::mutex C++11 并发之std::atomic ...

  3. C++11中的std::bind

    C++11中的std::bind 最近在看看cocos2dx的源代码,发现了cocos2dx 3.0相对于2.0改动了很多,最大的改变就是大量的使用了C++11的特性,比如auto等.其中有一个关于回 ...

  4. c++11 跨平台多线程demo和qt 静态链接(std::thread有join函数,设置 QMAKE_LFLAGS = -static)

    #include <stdio.h>#include <stdlib.h> #include <chrono> // std::chrono::seconds#in ...

  5. C++11 并发指南------std::thread 详解

    参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...

  6. C++11并发——多线程std::thread (一)

    https://www.cnblogs.com/haippy/p/3284540.html 与 C++11 多线程相关的头文件 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< ...

  7. C++随笔(1)——关于C++11中的线程创建,join和detach

    主要是和之前的博文有关,之前在这里有一部分代码是通过创建新的进程来应对新的用户请求的,但是基本没怎么解释怎么用的,所以这里做点小笔记. join 首先引入的库: #include <thread ...

  8. c++11并发之std::thread

    知识链接: https://www.cnblogs.com/lidabo/p/7852033.html 构造函数如下: ) thread() noexcept; initialization() te ...

  9. C++11 并发之std::thread std::mutex

    https://www.cnblogs.com/whlook/p/6573659.html (https://www.cnblogs.com/lidabo/p/7852033.html) C++:线程 ...

随机推荐

  1. 2019.02.09 bzoj2440: [中山市选2011]完全平方数(二分答案+容斥原理)

    传送门 题意简述:qqq次询问(q≤500)(q\le500)(q≤500),每次问第kkk个不被除111以外的完全平方数整除的数是多少(k≤1e9)(k\le1e9)(k≤1e9). 思路:考虑二分 ...

  2. 2019.01.10 bzoj1095: [ZJOI2007]Hide 捉迷藏(动态点分治)

    传送门 蒟蒻真正意义上做的第一道动态点分治! 题意:给一棵最开始所有点都是黑点的树,支持把点的颜色变成从黑/白色变成白/黑色,问当前状态树上两个最远黑点的距离. 思路: 首先考虑不带修改一次点分治怎么 ...

  3. ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树,倍增lca)

    https://nanti.jisuanke.com/t/31462 要求在一个矩形中任意选两个点都有唯一的通路,所以不会建多余的墙. 要求满足上述情况下,建墙的费用最小.理解题意后容易想到首先假设全 ...

  4. 振动器(Vibrator)

    package com.wwj.serviceandboardcast;   import android.app.Activity; import android.app.Service; impo ...

  5. Arria10 SDI II学习笔记

    12G-SDI16是什么意思? 关于 int_vpid_byte1 int_vpid_byte2 int_vpid_byte3 int_vpid_byte4 这些参数是不是如果外部数据有就不需要传输, ...

  6. 2.3.4volatile的原子性

    关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也不具备原子性. 测试 package com.cky.thread; /** * Created by edi ...

  7. (转)MVC语法-基础

    好久没有关注微软的开发了,今天看到了MVC3,顺便学习学习,我觉得Razor是个不错的做法,比使用<%%>简单多了,而且好看.首先“_”开头的cshtml文档将不能在服务器上访问,和asp ...

  8. java基础-day10

    第10天 IO 今日内容介绍 u IO流概述及FileWriter类使用 u FileReader类使用 u 缓冲流介绍和使用 u IO流相关案例 第1章   IO流概述及FileWriter类使用 ...

  9. spring-数据库操作组件的实现

    Ok,今天看了下spring数据库组件实现的源码,简要的做下笔记. 首先是JdbcTemplate,其实这个技术的实现很简单,就是一个模板类,把执行sql的主干流程都写好了,比如connection的 ...

  10. Hdu1205 吃糖果 2017-06-29 14:26 24人阅读 评论(0) 收藏

    吃糖果 Problem Description HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另 ...