线程没有调用join和detach

thread对象必须调用join或者detach,否则程序会终止

例如:

void func()
{
std::cout << "hello, " << std::this_thread::get_id() << std::endl;
} int main()
{
std::thread t(func);
return 0;
}

也可能在join/detach之前抛出异常导致没有正常调用join/detach

void func()
{
......
}
int main()
{
std::thread t(func);
......
where (......)
{
......
// 这里抛出异常
}
......
t.join();
return 0;
}

上面这段代码在where块里抛出异常导致join没有被调用

解决方法

第一种解决方法是加上try-catch块

......
try {
where () { ...... }
} catch (...) {
if (t.joinable())
t.join();
throw;
}
......
t.join();
......

或者使用RAII,将thread对象放到自定义类型classT中,在classT的析构方法里尝试调用join/detach

class Wrapper
{
public:
......
~Wrapper() { if (m_t.joinable()) m_t.join(); }
......
private:
std::thread m_t;
}

thread可以用任何callable对象构造

thread构造函数的第一个参数可以是任何callable对象:

  • 一般的函数调用,如上面func
  • 仿函数 Functor
  • Lambda函数
void func() { cout << "hello" << endl; }

class Functor
{
public:
void operator()
{
cout << "Functor" << endl;
}
} int main()
{
...
thread t1(func);
thread t2([](){ cout << "Lambda" << endl });
Functor fct;
thread t3(fct);
thread t4((Functor()));
// 注意这里不能用thread t4(Functor()),会被认为是一个函数声明,函数名为t4,返回值是thread类型的函数
...
// t1~t4调用join/detach
return 0;
}

传参

void func(string s) { cout << s << endl; }
...
string s = "hello";
thread t(func, s);

上面这张值传参方式存在多次string复制行为,使用引用传参可以减少一次复制行为,如下:

void func(string &str) { cout << str << endl; }
...
string s = "hello";
thread t(func, s);

但是上面这段代码仍然不是真正的引用传参,thread构造函数里的参数总是使用值传参。

也就是说如果在func里修改str,是不会影响到字符串s的。

处理方式是使用std::ref,实现真正的引用传参

void func(string &str);
...
string s = "hello";
thread t(func, std:;ref(s));

将指针作为参数传入

上面使用std::ref的例子也可以用指针传参实现,但是会让子线程和父线程有内存共享,会导致数据争用(data racing)

std::move

c++里很多类型的对象不支持复制,只能“移动”,例如thread对象就是可移动不可复制

thread t1(func);
// thread t2 = t1; // 错误!
thread t2 = std::move(t1); // 这时t1对象已经不能使用了

最多可以启动的线程数maxnum

当开启超过maxnum的线程时,效率不会提高反而会降低,因为这时cpu会进行上下文切换

用std::thread::hardware_concurrency()查看支持的最大线程数

c++11多线程记录2:线程管理的更多相关文章

  1. c++11多线程记录0

    两种并发编程模型 多进程 进程间通信常用的几种方式: 文件 管道 消息队列 多线程 一个进程中存在的多个线程,通常通过共享内存来通信,(说的非常非常粗俗,就是通过类似"全局变量"的 ...

  2. c++11多线程记录6:条件变量(condition variables)

    https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...

  3. c++11多线程记录5: Unique Lock和延时初始化

    https://www.youtube.com/user/BoQianTheProgrammer 视频网址 Unique Lock unique_lock和lock_guard类似,都是mutex的w ...

  4. c++11多线程记录4:死锁

    简单示例 举个例子,桌上有一支笔和一张纸,小A和小B都要拿到纸笔写字 小A拿了笔,小B拿了纸,这时就形成了死锁(两人都不愿意让出纸笔). 其实只要稍加控制就可以避免这种情况:规定必须先拿到纸再能去尝试 ...

  5. c++11多线程记录3: 数据争用和Mutex的使用

    https://www.youtube.com/watch?v=3ZxZPeXPaM4 学习视频 数据争用 简单来说就是存在多个线程同时对某个共同的对象进行读写(至少有一个线程在做写操作),造成读取这 ...

  6. c++11多线程记录1 -- std::thread

    启动一个线程 话不多说,直接上代码 void func(); int main() { std::thread t(func); //这里就开始启动线程了 t.join(); // 必须调用join或 ...

  7. c++11の简单线程管理

    1.简单的例子 #include "stdafx.h" #include <iostream> #include <thread> void functio ...

  8. C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

  9. (转)C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

随机推荐

  1. ESA2GJK1DH1K微信小程序篇: 安装Nginx,配置反向代理

    前言 一,为什么需要反向代理 小程序访问的是 443端口,咱需要把443端口的数据传给MQTT 这节为了避免大家配置出错,以下源码已经配置. 如果大家想自己配置,请参考 https://www.cnb ...

  2. [RN] React Native :Error: Cannot find module 'asap/raw'

    今天在使用 react-native-dropdownmenus 的时候,安装没问题,但Link的时候 报: Error: Cannot find module 'asap/raw' 朋友们莫慌,一步 ...

  3. LCA的几种做法

    P3379 LCA $ 1:$蜗牛爬式 void dfs(int u,int fa) { f[u]=fa;//预处理father for(int i=head[u]; i; i=e[i].nxt) i ...

  4. 一大波 Facebook Libra 技术文章来袭

    由于 Libra 具有真正的稳定的可编程货币的特性, Libra 或许可以带来又一波平台红利. 上周我们(深入浅出区块链技术社区)发起了 Libra 技术文档的翻译计划,到这周文档已经翻译了一半.欢迎 ...

  5. 禁用F12,屏蔽鼠标右击、

    $(document).ready(function(){ $(document).bind("contextmenu",function(e){ return false; }) ...

  6. [技术博客] SPRINGBOOT自定义注解

    SPRINGBOOT自定义注解 在springboot中,有各种各样的注解,这些注解能够简化我们的配置,提高开发效率.一般来说,springboot提供的注解已经佷丰富了,但如果我们想针对某个特定情景 ...

  7. leetcode 494. 目标数

    题目描述: 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面. 返回可以 ...

  8. Delaunay和Voronoi

    什么是Delaunay三角剖分? 图1:Delaunay三角剖分偏爱小角度 给定平面中的一组点,三角剖分指的是将平面细分为三角形,这些点为顶点.在图1中,我们在左侧图像上看到了一组地标,在中间图像上看 ...

  9. 直接从ADB接出串口调试

    1,从硬件接出串口线 2,用串口工具连接上串口工具,串口工具地址:https://files.cnblogs.com/files/senior-engineer/%E4%B8%B2%E5%8F%A3% ...

  10. 使用trace文件分析ANR

    2017年02月07日 12:32:45 不死鸟JGC 阅读数 13886更多 分类专栏: Android   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链 ...