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. 安装使用composer基本流程

    composer工作原理: 这里经过几个步骤:1.composer读取composer.json(这个文件手动建立,官网有格式),这个json是在当前执行composer目录的,如果目录下没有这个js ...

  2. 使用 Vue.js 结合bootstrap 实现的分页控件

    原文链接:http://blog.csdn.net/qiuhaotc/article/details/53031884 源码下载: http://pan.baidu.com/s/1i4XgH6H 密码 ...

  3. 20145118 《Java程序设计》课程总结

    20145118 <Java程序设计>课程总结 每周读书笔记连接汇总 假期笔记 http://www.cnblogs.com/cy1123/p/5224305.html 第一周读书笔记 h ...

  4. ReadResolve方法与序列化

    使用枚举实现的单例模式,不但可以防止利用反射强行构建单例对象,而且可以在枚举类对象被反序列化的时候,保证反序列的返回结果是同一对象. 对于其他方式实现的单例模式,如果既想要做到可序列化,又想要反序列化 ...

  5. SQL NULL

    表 select CHARACTER_MAXIMUM_LENGTH from information_schema.columns where table_name= 'Alliance' selec ...

  6. [bzoj1571][Usaco2009 Open]滑雪课Ski

    题目描述 Farmer John 想要带着 Bessie 一起在科罗拉多州一起滑雪.很不幸,Bessie滑雪技术并不精湛. Bessie了解到,在滑雪场里,每天会提供S(0<=S<=100 ...

  7. MariaDB / MySQL数据类型

    MariaDB / MySQL 数据类型 有三种主要的类型:Text(文本).Number(数字)和 Date/Time(日期/时间)类型. Text 类型: 数据类型 描述 CHAR(size) 保 ...

  8. BZOJ 1010: [HNOI2008]玩具装箱toy(斜率优化dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题意: 思路: 容易得到朴素的递归方程:$dp(i)=min(dp(i),dp(k)+(i-k ...

  9. UVa 11054 Gergovia的酒交易

    https://vjudge.net/problem/UVA-11054 题意:直线上有n个等距的村庄,每个村庄要么买酒,要么卖酒.设第i个村庄对酒的需求为ai,ai>0表示买酒,ai<0 ...

  10. MVC ---- DBHelper.ttinclude

    在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实战篇.T4模板引擎可以当做一个代码生成器,代码生成器的职责当然是用来生成代码(这不是废话吗).而这其中我们使用的最普遍的是根据数据库生成实 ...