c++11多线程记录2:线程管理
线程没有调用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:线程管理的更多相关文章
- c++11多线程记录0
两种并发编程模型 多进程 进程间通信常用的几种方式: 文件 管道 消息队列 多线程 一个进程中存在的多个线程,通常通过共享内存来通信,(说的非常非常粗俗,就是通过类似"全局变量"的 ...
- c++11多线程记录6:条件变量(condition variables)
https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...
- c++11多线程记录5: Unique Lock和延时初始化
https://www.youtube.com/user/BoQianTheProgrammer 视频网址 Unique Lock unique_lock和lock_guard类似,都是mutex的w ...
- c++11多线程记录4:死锁
简单示例 举个例子,桌上有一支笔和一张纸,小A和小B都要拿到纸笔写字 小A拿了笔,小B拿了纸,这时就形成了死锁(两人都不愿意让出纸笔). 其实只要稍加控制就可以避免这种情况:规定必须先拿到纸再能去尝试 ...
- c++11多线程记录3: 数据争用和Mutex的使用
https://www.youtube.com/watch?v=3ZxZPeXPaM4 学习视频 数据争用 简单来说就是存在多个线程同时对某个共同的对象进行读写(至少有一个线程在做写操作),造成读取这 ...
- c++11多线程记录1 -- std::thread
启动一个线程 话不多说,直接上代码 void func(); int main() { std::thread t(func); //这里就开始启动线程了 t.join(); // 必须调用join或 ...
- c++11の简单线程管理
1.简单的例子 #include "stdafx.h" #include <iostream> #include <thread> void functio ...
- C++ 11 多线程--线程管理
说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...
- (转)C++ 11 多线程--线程管理
说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...
随机推荐
- MongoDB 企业版4.2.2安装
一.下载企业版MongoDB安装RPM包 https://www.mongodb.com/download-center/enterprise 二.安装MogoDB4.2.2企业版 1.安装依赖包 n ...
- JS的ES6扩展
1.字符串扩展 1. includes(str) : 判断是否包含指定的字符串 2. startsWith(str) : 判断是否以指定字符串开头 3. endsWith(str) : 判断是否以指定 ...
- MYSQL索引的作用和创建
索引是查询优化最主要的方式: 查询方式: 一种是:全表扫描: 一种是:利用数据表上建立的所以进行扫描. 如:对表中name字段建立索引:则按照表中name字段进行索引排序,并为其建立指向数据表中记录所 ...
- 洛谷 P1621 集合
目录 题目 思路 \(Code\) 题目 P1621 集合 思路 并查集+埃氏筛,一开始连通块的个数是\(b-a+1\)个,在筛素数的过程中只要当前素数大于\(p\)就对该素数筛出来的数进行判断,如果 ...
- yarn和npm的对比,以及项目中使用方式
相比npm 的优点 1.npm安装是串行,而yarn是并行,速度大大提升 2.已经下载过的包会被缓存,无需重复下载,更关键的是,支持离线安装 3.精准的版本控制,加上验证每个包的完整性,保证每次安装的 ...
- centos服务器升级nodejs, pm2
突然抽风想升级服务器的nodejs版本,原服务器版本运行的8.x,而目前(2019年5月30日)nodejs官方最新版本已经更新到了12.x了,稳定版本也更新到了10.x. 然后就折腾了一把去升级服务 ...
- GoCN每日新闻(2019-11-04)
GoCN每日新闻(2019-11-04) GoCN每日新闻(2019-11-04) 1. Go中垃圾收集器是如何标记内存的 https://medium.com/a-journey-with-go ...
- Linux防火墙配置方法
1)查看防火墙状态 查看防火墙状态: /etc/init.d/iptables status 暂时关闭防火墙: /etc/init.d/iptables stop 重启防火墙: /etc/init.d ...
- 前端微服务初试(singleSpa)
1.基本概念 实现一套微前端架构,可以把其分成四部分(参考:https://alili.tech/archive/11052bf4/) 加载器:也就是微前端架构的核心,主要用来调度子应用,决定何时展示 ...
- Ubuntu 19.04 国内更新源
2019年4月18日, Ubuntu 19.04 正式发布. Ubuntu 19.04 的 Codename 是"disco(迪斯科舞厅)": zkf@ubuntu:~$ lsb_ ...