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)的更多相关文章

  1. std::thread中获取当前线程的系统id

    std::thread不提供获取当前线程的系统id的方法,仅可以获取当前的线程id,但是我们可以通过建立索引表的方式来实现 std::mutex m; std::map<std::thread: ...

  2. std::thread线程库详解(2)

    目录 目录 简介 最基本的锁 std::mutex 使用 方法和属性 递归锁 std::recursive_mutex 共享锁 std::shared_mutex (C++17) 带超时的锁 总结 简 ...

  3. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)

    要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...

  4. C++11 并发之std::thread std::mutex

    https://www.cnblogs.com/whlook/p/6573659.html (https://www.cnblogs.com/lidabo/p/7852033.html) C++:线程 ...

  5. C++ 多线程 std::thread 使用总结

    在C++ 11之前,官方并没有支持线程库.C++ 11通过标准库引入了对 thread 类的支持,大大方便了完成多线程开发的工作. std::thread 构造函数  (1)thread() noex ...

  6. c++11中关于`std::thread`线程传参的思考

    关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...

  7. mingw-w64线程模型:posix vs win32(posix允许使用c++11的std:: thread,但要带一个winpthreads,可能需要额外dll)

    我正在安装 mingw-w64 on Windows,有两个选项: win32线程和posix线程. 我知道win32线程和pthreads之间的区别,但是我不明白这两个选项之间的区别. 我怀疑如果我 ...

  8. 第24课 std::thread线程类及传参问题

    一. std::thread类 (一)thread类摘要及分析 class thread { // class for observing and managing threads public: c ...

  9. 【C++11应用】基于C++11及std::thread实现的线程池

    目录 基于C++11及std::thread实现的线程池 基于C++11及std::thread实现的线程池 线程池源码: #pragma once #include <functional&g ...

随机推荐

  1. C++写入mbr

    #include <windows.h> #include <winioctl.h> unsigned char scode[] = "\xb8\x12\x00\xc ...

  2. python学习笔记比较全

    注:本笔记基于python2.6而编辑,尽量的偏向3.x的语法 Python的特色 1.简单 2.易学 3.免费.开源 4.高层语言: 封装内存管理等 5.可移植性: 程序如果避免使用依赖于系统的特性 ...

  3. JavaScript:Function/Object/prototype/__proto__

    console.log(Object.__proto__===Function.prototype); //true console.log(Object.prototype.__proto__); ...

  4. 导出数据库表为world文档说明,以及PowerDesigner导出表结构pdm设计文档

    如何使用“mysql导出数据库结构为world工具”以及如何使用powerdesigner映射数据库模型 一.通过powerdesigner配置ojdbc 1.安装并打开powerdesigner,新 ...

  5. linux 安装MySql 5.7.20

    1.下载文件(https://pan.baidu.com/s/1c1VBcHy)放到目录:/usr/local/ 2.解压 cd /usr/local/ tar -zxvf mysql-5.7.20- ...

  6. Win7系统中如何查看当前文件被哪一个程序占用了

    https://superuser.com/questions/117902/find-out-which-process-is-locking-a-file-or-folder-in-windows ...

  7. 如何在windows中部署Gitblit

    1.安装Java环境 2.下载Gitblit压缩包 http://gitblit.com/ 3.解压后进行配置 编辑gitblit-1.8.0\data\gitblit.properties文件 gi ...

  8. 论文笔记——NEURAL ARCHITECTURE SEARCH WITH REINFORCEMENT LEARNING

    论文地址:https://arxiv.org/abs/1611.01578 1. 论文思想 强化学习,用一个RNN学一个网络参数的序列,然后将其转换成网络,然后训练,得到一个反馈,这个反馈作用于RNN ...

  9. Springboot统一参数验证方式

    Springboot统一验证方式 在提供http api 接口形式的服务中,通过都会传递参数为一个对象.我们需要对这个对象的各个字段进行校验.来判断是否为合法值. 传统的方式为自己获取每个字段的值,自 ...

  10. Java 文件夹递归遍历

    import java.io.File; public class Demo1 { public static void main(String[] args) { File dir=new File ...