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 ...
随机推荐
- 开源项目托管GitHub
工具:本地HelloWorld源项目 msysgit(Windows) 实验步骤:一.在GitHub新建托管项目 在http://github.com注册账号20159214-sunnan. 完成注册 ...
- Win32程序支持命令行参数的做法(转载)
转载:http://www.cnblogs.com/lanzhi/p/6470406.html 转载:http://blog.csdn.net/kelsel/article/details/52759 ...
- 【资源】分享一个最新版sublime 3143的注册码,亲测可用
注:请勿用作商业用途,有能力者请购买正版!!! —– BEGIN LICENSE —– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD9 ...
- hdu 6180 Schedule
Schedule Problem Description There are N schedules, the i-th schedule has start time si and end time ...
- Linux下替换默认版本的protobuf
1. 下载 下载地址,我下载的是protobuf-all-3.5.0.tar.gz,尽量下载all,里面包含protobuf库的所有文件. 2. 编译 ./configure make make in ...
- java对象在内存的大小
前言 一直以来,对java对象大小的概念停留在基础数据类型,比如byte占1字节,int占4字节,long占8字节等,但是一个对象包含的内存空间肯定不只有这些. 假设有类A和B,当new A()或者n ...
- P4-Related Tools Installation
P4-Related Tools Installation 安装P4相关工具的步骤和说明. 本说明只适用于 Ubuntu 14.04 系统. 推荐安装的其他工具 mininet:SDN网络仿真工具 v ...
- 01_Spark基础
1.1.Spark Ecosystem BlinkDB: 允许用户定义一个错误范围,BlinkDB将在用户给定的错误范围内,尽可能快的提供查询结果 1.2.Spark愿景 1.3.Spark简介 1) ...
- HDU 2586 How far away ?(LCA在线算法实现)
http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...
- H5本地存储一
localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用.sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同 ...