C++:线程(std::thread)
1.创建一个线程
创建线程比较简单,使用std的thread实例化一个线程对象就创建完成了,示例:
#include <iostream>
#include <thread>
using namespace std; void t1() //普通的函数,用来执行线程
{
for (int i = ; i < ; ++i)
{
cout << "t1111\n";
}
}
void t2()
{
for (int i = ; i < ; ++i)
{
cout << "t22222\n";
}
}
int main()
{
thread th1(t1); //实例化一个线程对象th1,使用函数t1构造,然后该线程就开始执行了(t1())
thread th2(t2); cout << "here is main\n\n"; return ;
}
不过这个示例是有问题的,因为在创建了线程后线程开始执行,但是主线程main()并没有停止脚步,仍然继续执行然后退出,此时线程对象还是joinable的,线程仍然存在但指向它的线程对象已经销毁,所以会抛出异常。

那么该如何保证子线程执行完了退出后再退出主线程呢?
2.thread::join()
使用join接口可以解决上述问题,join的作用是让主线程等待直到该子线程执行结束,示例:
#include <iostream>
#include <thread>
using namespace std; void t1()
{
for (int i = ; i < ; ++i)
{
cout << "t1111\n";
}
}
void t2()
{
for (int i = ; i < ; ++i)
{
cout << "t22222\n";
}
}
int main()
{
thread th1(t1);
thread th2(t2); th1.join(); //等待th1执行完
th2.join(); //等待th2执行完 cout << "here is main\n\n"; return ;
}
此时就可以正常地执行子线程了,同时注意最后一个输出,说明了main是等待子线程结束才继续执行的

需要注意的是线程对象执行了join后就不再joinable了,所以只能调用join一次。
3.thread::detach()
(1.)中提到的问题,还可以使用detach来解决,detach是用来和线程对象分离的,这样线程可以独立地执行,不过这样由于没有thread对象指向该线程而失去了对它的控制,当对象析构时线程会继续在后台执行,但是当主程序退出时并不能保证线程能执行完。如果没有良好的控制机制或者这种后台线程比较重要,最好不用detach而应该使用join。
int main()
{
thread th1(t1);
thread th2(t2); th1.detach();
th2.detach(); cout << "here is main\n\n"; return ;
}
由结果可见线程并没有执行完而退出:

4.mutex
头文件是<mutex>,mutex是用来保证线程同步的,防止不同的线程同时操作同一个共享数据。
int cnt = ;
mutex m;
void t1()
{
while (cnt > )
{
m.lock(); if (cnt > )
{
--cnt;
cout << cnt << endl;
} m.unlock();
}
}
void t2()
{
while (cnt > )
{
m.lock(); if (cnt > )
{
--cnt;
cout << cnt << endl;
} m.unlock();
}
}
int main()
{ thread th1(t1);
thread th2(t2); th1.join();
th2.join(); return ;
}
运行结果,cnt是依次递减的,没有因为多线程而打乱次序:

但是使用mutex是不安全的,当一个线程在解锁之前异常退出了,那么其它被阻塞的线程就无法继续下去。
5.std::lock_guard
使用lock_guard则相对安全,它是基于作用域的,能够自解锁,当该对象创建时,它会像m.lock()一样获得互斥锁,当生命周期结束时,它会自动析构(unlock),不会因为某个线程异常退出而影响其他线程。示例:
int cnt = ;
mutex m;
void t1()
{
while (cnt > )
{
lock_guard<mutex> lockGuard(m);
if (cnt > )
{
--cnt;
cout << cnt << endl;
} }
}
void t2()
{
while (cnt > )
{
lock_guard<mutex> lockGuard(m);
if (cnt > )
{
--cnt;
cout << cnt << endl;
} }
}
C++:线程(std::thread)的更多相关文章
- std::thread中获取当前线程的系统id
std::thread不提供获取当前线程的系统id的方法,仅可以获取当前的线程id,但是我们可以通过建立索引表的方式来实现 std::mutex m; std::map<std::thread: ...
- std::thread线程库详解(2)
目录 目录 简介 最基本的锁 std::mutex 使用 方法和属性 递归锁 std::recursive_mutex 共享锁 std::shared_mutex (C++17) 带超时的锁 总结 简 ...
- C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)
要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...
- C++11 并发之std::thread std::mutex
https://www.cnblogs.com/whlook/p/6573659.html (https://www.cnblogs.com/lidabo/p/7852033.html) C++:线程 ...
- C++ 多线程 std::thread 使用总结
在C++ 11之前,官方并没有支持线程库.C++ 11通过标准库引入了对 thread 类的支持,大大方便了完成多线程开发的工作. std::thread 构造函数 (1)thread() noex ...
- c++11中关于`std::thread`线程传参的思考
关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...
- mingw-w64线程模型:posix vs win32(posix允许使用c++11的std:: thread,但要带一个winpthreads,可能需要额外dll)
我正在安装 mingw-w64 on Windows,有两个选项: win32线程和posix线程. 我知道win32线程和pthreads之间的区别,但是我不明白这两个选项之间的区别. 我怀疑如果我 ...
- 第24课 std::thread线程类及传参问题
一. std::thread类 (一)thread类摘要及分析 class thread { // class for observing and managing threads public: c ...
- 【C++11应用】基于C++11及std::thread实现的线程池
目录 基于C++11及std::thread实现的线程池 基于C++11及std::thread实现的线程池 线程池源码: #pragma once #include <functional&g ...
随机推荐
- 20145307陈俊达_安卓逆向分析_dex2jar&jd-gui的使用
20145307陈俊达_安卓逆向分析_dex2jar&jd-gui的使用 引言 这次免考选择了四个项目,难度也是从简到难,最开始先写一个工具的使用 想要开发安卓首先要会编写代码,但是想要逆向分 ...
- 20165211 预备作业3 Linux安装与学习
20165211 预备作业3 Linux安装与学习 1. Linux安装 涉及软件:VirtualBox,Ubuntu 参考教程:基于VirtualBox安装Ubuntu图文教程 安装过程的问题 在安 ...
- 《Python程序设计(第3版)》[美] 约翰·策勒(John Zelle) 第 4 章 答案
判断对错 1.利用 grAphiCs.py 可以在 Python 的 shell 窗口中绘制图形.2.传统上,图形窗口的左上角坐标为(0,0).3.图形屏幕上的单个点称为像素.4.创建类的新实例的函数 ...
- Python3基础 生成器推导式 简单示例
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- fhq treap抄袭笔记
目录 碎碎念 点一下 注意!!! 模板 fhq treap 碎碎念 我咋感觉合并这么像左偏树呢 ps:难道你们的treap都是小头堆的吗 fhq真的是神人 现在看以前学的splay是有点恶心,尤其是压 ...
- 终于在nowcoder爆发了的懒惰
题目 这类题目我实在忍不了了 Emma,随便做个nowcode比赛题吧,我在oj上也没找到 题意 求\(\sum_{L=1}^{n}\sum_{R=i}^{n}a[k](L<=k<=R)\ ...
- 自定义redis序列化工具
redis一个优点就是可以将数据写入到磁盘中. 我们知道写入磁盘的数据实际上都是以字节(0101这样的二进制数据)的形式写入的. 这意味着如果我们要将一个对象写入磁盘,就必须将这个对象序列化. jav ...
- Intellij新建Spring项目引入用户目录下的Spring jar包
首先,在IntelliJ IDEA中新建module,选择Spring应用: 在初次使用时,如果IDE检测到本地没有spring核心库,则会在新建过程中下载对应库文件,在使用spring框架时,可 ...
- org.apache.axis2.AxisFault: unknown
遇到这个异常懵逼了很长时间才解决,axis2框架个人感觉进行接口相互调用还是比较麻烦的, 调了很长时间,我由a项目调用b项目的接口时,一直报这个错,在网上找了很长时间,也没找到 解决的办法,自己慢慢的 ...
- BZOJ 2467: [中山市选2010]生成树(矩阵树定理+取模高斯消元)
http://www.lydsy.com/JudgeOnline/problem.php?id=2467 题意: 思路:要用矩阵树定理不难,但是这里的话需要取模,所以是需要计算逆元的,但是用辗转相减会 ...