线程没有调用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. Numpy | 10 广播(Broadcast)

    广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行. 下面的图片展示了数组 b 如何通过广播来与数组 a 兼容. 4x ...

  2. ent 基本使用十三 debug 模式

    ent 生成的代码client 包中包含了一个方便的方法Debug(), 记得昨天我为了查看生成的sql 查询通过配置mysql 启用慢查询,同时设置记录慢查询为0,实际上client Debug 方 ...

  3. 洛谷p2370yyy2015c01的U盘题解

    没什么特殊的想法 就是看自己很久没有更新关于题解类的文章了而已 (其实这是我好久之前做的, 只是把它从洛谷博客搬到了这里而已) 题目 首先分析题目要二分 他长成这个亚子太二分了 所以就要二分 最好是先 ...

  4. PHP Record the number of login users

    Function to record how many times the user logs in Connect to the database first: you can create a n ...

  5. Centos pip 安装uwsgi 报错“fatal error: Python.h: No such file or directory”

    解决方法: 安装python-devel即可,注意,不是python-dev yum -y install python-devel

  6. Spring事务经典案例-银行转账

    1.entity实体类 2.dao层 3.dao实现类 4.service层 5.serviceimpl层 6.大配置.xml <?xml version="1.0" enc ...

  7. vlc for mac设置中文的方法

    VLC for mac是一款mac系统下的多媒体播放器,支持播放MPEG-1.MPEG-2.MPEG-4.DivX.MP3和OGG,以及DVD.VCD.等各种流媒体协议在内的多种协议格式,并且能够对电 ...

  8. 第08组 Alpha冲刺(2/4)

    队名 八组评分了吗 组长博客 小李的博客 作业博客 作业链接 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 11月17日了解各个小组的进度与难以攻破的地方,与隔壁第七组组长讨论进度发展 ...

  9. javascript的Map使用

    setExpenseAndAmountSum: function() { var detailList = vehicleVueObj.vehicleData; var expenseAmountSu ...

  10. windows命令行将应用程序加入环境变量

    1.命令行方法,最快(推荐): 1.1.获取应用安装绝对路径: 方法一:一层层点进去,然后复制路径栏目:方法二:打开软件执行文件所在目录,按住shift点击鼠标邮件,选择powerShell,现在wi ...