thread::join(): 阻塞当前线程,直至 *this 所标识的线程完成其执行。*this 所标识的线程的完成同步于从 join() 的成功返回。

该方法简单暴力,主线程等待子进程期间什么都不能做。thread::join()会清理子线程相关的内存空间,此后thread object将不再和这个子线程相关了,即thread object不再joinable了,所以join对于一个子线程来说只可以被调用一次,为了实现更精细的线程等待机制,可以使用条件变量等机制。

#include <iostream>
#include <thread>
#include <chrono> void foo()
{
std::cout << "foo is started\n";
// 模拟昂贵操作
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "foo is done\n";
} void bar()
{
std::cout << "bar is started\n";
// 模拟昂贵操作
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "bar is done\n";
} int main()
{
std::cout << "starting first helper...\n";
std::thread helper1(foo); std::cout << "starting second helper...\n";
std::thread helper2(bar); std::cout << "waiting for helpers to finish...\n" << std::endl;
helper1.join();
helper2.join(); std::cout << "done!\n";
}

运行结果:

starting first helper...
starting second helper...
foo is started
waiting for helpers to finish...
bar is started foo is done
bar is done
done!

异常环境下join,假设主线程在一个函数f()里面创建thread object,接着f()又调用其它函数g(),那么确保在g()以任何方式下退出主线程都能join子线程。如:若g()通过异常退出,那么f()需要捕捉异常后join.

#include<iostream>
#include<boost/thread.hpp>
void do_something(int& i){
i++;
}
class func{
public:
func(int& i):i_(i){}
void operator() (){
for(int j=;j<;j++)
do_something(i_);
}
public:
int& i_;
};
void do_something_in_current_thread(){}
void f(){
int local=;
func my_func(local);
boost::thread t(my_func);
try{
do_something_in_current_thread();
}
catch(...){
t.join();//确保在异常条件下join子线程
throw;
}
t.join();
}
int main(){
f();
return ;
}

上面的方法看起来笨重,有个解决办法是采用RAII(资源获取即初始化),将一个thread object通过栈对象A管理,在栈对象A析构时调用thread::join.按照局部对象析构是构造的逆序,栈对象A析构完成后再析构thread object。如下:

#include<iostream>
#include<boost/noncopyable.hpp>
#include<boost/thread.hpp>
using namespace std;
class thread_guard:boost::noncopyable{
public:
explicit thread_guard(boost::thread& t):t_(t){}
~thread_guard(){
if(t_.joinable()){//检测是很有必要的,因为thread::join只能调用一次,要防止其它地方意外join了
t_.join();
}
}
//thread_guard(const thread_guard&)=delete;//c++11中这样声明表示禁用copy constructor需要-std=c++0x支持,这里采用boost::noncopyable已经禁止了拷贝和复制
//thread_guard& operator=(const thread_guard&)=delete;
private:
boost::thread& t_;
};
void do_something(int& i){
i++;
}
class func{
public:
func(int& i):i_(i){}
void operator()(){
for(int j=;j<;j++)
do_something(i_);
}
public:
int& i_;
};
void do_something_in_current_thread(){}
void fun(){
int local=;
func my_func(local);
boost::thread t(my_func);
thread_guard g(t);
do_something_in_current_thread();
}
int main(){
fun();
return ;
}

thread::detach(): 从 thread 对象分离执行的线程,允许执行独立地持续。一旦线程退出,则释放所有分配的资源。调用 detach 后, *this 不再占有任何线程。

#include <iostream>
#include <chrono>
#include <thread> void independentThread()
{
std::cout << "Starting concurrent thread.\n";
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "Exiting concurrent thread.\n";
} void threadCaller()
{
std::cout << "Starting thread caller.\n";
std::thread t(independentThread);
t.detach();
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "Exiting thread caller.\n";
} int main()
{
threadCaller();
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "back to main.\n";
}

运行结果:

Starting thread caller.
Starting concurrent thread.
Exiting thread caller.
Exiting concurrent thread.
back to main.

如果注释掉main函数里的std::this_thread::sleep_for(std::chrono::seconds(5)); 即不等待independentThread 执行完。运行结果如下:

Starting thread caller.
Starting concurrent thread.
Exiting thread caller.
back to main.

c++并发编程之thread::join()和thread::detach()的更多相关文章

  1. 并发编程之Fork/Join

    并发与并行 并发:多个进程交替执行. 并行:多个进程同时进行,不存在线程的上下文切换. 并发与并行的目的都是使CPU的利用率达到最大.Fork/Join就是为了尽可能提高硬件的使用率而应运而生的. 计 ...

  2. 并发编程之fork/join(分而治之)

    1.什么是分而治之 分而治之就是将一个大任务层层拆分成一个个的小任务,直到不可拆分,拆分依据定义的阈值划分任务规模. fork/join通过fork将大任务拆分成小任务,在将小任务的结果join汇总 ...

  3. python并发编程之Queue线程、进程、协程通信(五)

    单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ...

  4. python并发编程之threading线程(一)

    进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源. 系列文章 py ...

  5. 并发编程之:JMM

    并发编程之:JMM 大家好,我是小黑,一个在互联网苟且偷生的农民工. 上一期给大家分享了关于Java中线程相关的一些基础知识.在关于线程终止的例子中,第一个方法讲到要想终止一个线程,可以使用标志位的方 ...

  6. 并发编程之:Atomic

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 在开始讲今天的内容之前,先问一个问题,使用int类型做加减操作是不是线程安全的呢?比如 i++ ,++i,i=i+1这样的操作在并发情况下是否会有问题 ...

  7. 并发编程之:CountDownLatch

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 先问大家一个问题,在主线程中创建多个线程,在这多个线程被启动之后,主线程需要等子线程执行完之后才能接着执行自己的代码,应该怎么实现呢? Thread. ...

  8. 并发编程之wait()、notify()

    前面的并发编程之volatile中我们用程序模拟了一个场景:在main方法中开启两个线程,其中一个线程t1往list里循环添加元素,另一个线程t2监听list中的size,当size等于5时,t2线程 ...

  9. 并发编程之 Exchanger 源码分析

    前言 JUC 包中除了 CountDownLatch, CyclicBarrier, Semaphore, 还有一个重要的工具,只不过相对而言使用的不多,什么呢? Exchange -- 交换器.用于 ...

  10. 并发编程之 Condition 源码分析

    前言 Condition 是 Lock 的伴侣,至于如何使用,我们之前也写了一些文章来说,例如 使用 ReentrantLock 和 Condition 实现一个阻塞队列,并发编程之 Java 三把锁 ...

随机推荐

  1. debian系统下改语言设置

    debian系统下改语言设置 安装debian 的时候选择了中文zh_CN_UTF-8,然后进系统后想换成en_US_UTF-8 可以使用一下命令选择:找到需要的语言 确定即可 dpkg-reconf ...

  2. noip 提高组 2010

    T1:机器翻译 题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英 ...

  3. Docker_容器化gitlab

    Docker部署接口自动化持续集成环境第一步,容器化一个Gitlab! 1:开放防火墙端口 sudo yum install curl openssh-server openssh-clients p ...

  4. 3dmax2020下载安装3dmax2020破解中文版下载安装

    3dmax在室内设计.建筑设计领域是最专业的效果图制作软件,也是在游戏动画等领域中在场景方面最专业的软件,目前最新3dmax2020版本已出,我分享亲测好用的软件包,拿走不谢! 3dmax2020安装 ...

  5. proe工程图输出dwg/dxf文件设置

    网上看到不少人分享proe转转dxf/dwg配置文件的,但是看了一圈,几乎都没有涉及到转化线型的,所以自己整理自己的配置文件,写在这里分享出来. 以Pro/engineer WF5.0为例: 1.复制 ...

  6. CDH 5.16.1 离线部署 & 通过 CDH 部署 Hadoop 服务

    参考 Cloudera Enterprise 5.16.x Installing Cloudera Manager, CDH, and Managed Services Installation Pa ...

  7. DevOps架构下如何进行微服务性能测试?

    一. 微服务架构下的性能测试挑战 微服务与DevOps 微服务是实现DevOps的重要架构 微服务3S原则 DevOps核心点 微服务架构下的业务特点 亿级用户的平台 单服务业务随时扩容 服务之间存在 ...

  8. LeetCode-3.无重复字符的最长字串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  9. Linux内核实验作业六

    实验作业:分析Linux内核创建一个新进程的过程 20135313吴子怡.北京电子科技学院 [第一部分]阅读理解task_struct数据结构 1.进程是计算机中已运行程序的实体.在面向线程设计的系统 ...

  10. hadoop-2.7.2 分布式集群搭建

    1.机器信息 五台centos 64位机器 2.集群规划 Server Name Hadoop Cluster Zookeeper   Ensemble HBase Cluster Hadoop01 ...