线程没有调用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. JS稀奇古怪题目

    JS稀奇古怪题目: 1.操作对象属性优先级高于普通赋值操作 var a = { n: 1 }; var b = a; //操作对象属性优先级高于普通赋值操作 a.x = a = { n: 2 }; c ...

  2. Mac Sublime Text使用python3运行脚本(command+b)

    默认安装好sublime, 使用快捷键command+b的时候, 会使用python2版本运行 下面就改为用python3运行, 也可以python2运行 一. 新建文件 Sublime Text - ...

  3. luogu P1725 琪露诺

    二次联通门 : luogu P1725 琪露诺 /* luogu P1725 琪露诺 DP + 线段树 用线段树维护dp[i - R] ~ dp[i - L]的最大值 然后 转移方程是 dp[i] = ...

  4. js中实现函数防抖跟函数节流

    最近刚接触两个新概念函数防抖与函数节流,虽然这些内容网上可以搜到很多,大家都有自己的一套的理解方式,都写得很好, 而自己则想在理解的基础上自己把代码实现一遍,加深印象. 一.函数防抖 假如我们有这样的 ...

  5. Python-DDT框架

    Install pip install ddt 实例 import unittest from ddt import ddt, data, unpack @ddt class MyTestCase(u ...

  6. 【转】聊聊并发(一)——深入分析Volatile的实现原理

    即两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件(race condition). 引言 在多线程并发编程中synchronized和Volatile都扮演着重要的 ...

  7. spring MVC cors跨域实现源码解析 CorsConfiguration UrlBasedCorsConfigurationSource

    spring MVC cors跨域实现源码解析 spring MVC cors跨域实现源码解析 名词解释:跨域资源共享(Cross-Origin Resource Sharing) 简单说就是只要协议 ...

  8. anaconda 安装指定源的包

    当前知道的有两种方式可以查找: 1.conda search 命令:conda search pkg_name 安装的时候直接:conda install cudatoolkit=版本后 conda ...

  9. Spark无法读取hive 3.x的表数据

    通过Ambari2.7.3安装HDP3.1.0成功之后,通过spark sql去查询hive表的数据发现竟然无法查询 HDP3.0 集成了hive 3.0和 spark 2.3,然而spark却读取不 ...

  10. wms证书异常问题

    目前我司已定位到两个原因,详细如下, 1.  快速生成的证书存在问题,导致APACHE和NGINX显示的时间都是4号凌晨 2.  贵司在配置完成162和163两台应用的APACHE证书,以及其中10. ...