c++11 Thread库之使写多线程程序
2017-11-07 13:23
323 查看
漫谈c++11 Thread库之使写多线程程序
c++11中最重要的特性之一就是对多线程的支持了,然而《c++ primer》5th却没有这部分内容的介绍,着实人有点遗憾。在网上了解到了一些关于thread库的内容。这是几个比较不错的学习thread库的资源:
Thread support library : http://en.cppreference.com/w/cpp/thread
Cpp reference/thread : http://www.cplusplus.com/reference/thread/
<< C++ Concurrency In Action >> :http://files.cnblogs.com/files/ittinybird/CplusplusConcurrencyInAction.pdf
//Recommend!
前两个网站我还是非常喜欢的,都是在线的帮助手册,两个选择其中一个就可以了,看你口味选择就好了。最后一个是原版的《C++ Concurrency In Action》,非常棒的一本书,鉴于中文译版已经被黑出翔了,所以能看英文就看英文版吧,我也是硬着头皮啃了一点儿。以下是我学习thread库的一点感受和见解,如果你有发现我的错误,还请你及时批评指正,我将万分感谢。
有关线程、并发相关的基础知识,我就不浪费篇幅了。
一个简单的使用线程的Demo
c++11提供了一个新的头文件<thread>提供了对线程函数的支持的声明(其他数据保护相关的声明放在其他的头文件中,暂时先从thread头文件入手吧),写一个多线程的程序需要引用这个新的头文件:
那么程序的执行流是如何从main()转去执行fun()的呢,下面我们先看看thread这个类。
线程的启动
我的环境是CentOS7 + g++4.8.3 头文件/usr/include/c++/4.8.3/thread中有thread类的完整声明(我的windows环境是win8.1+vs2013,在默认安装的情况下thread头文件的路径是C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\thread)。代码太长,我就不贴出来了。c++线程库通过构造一个线程对象,来启动一个线程。那么我们就先来看一下thread的构造函数:
以下贴出thread类的代码均是出自GNU的实现版本
template<typename _Callable, typename... _Args>
explicit thread(_Callable&& __f, _Args&&... __args);
可以清楚的看见它把参数都交给了std::__bind_simple()处理了,而对于std::__bind_simple()的定义在其头文件<functional>中,和std::bind()的用法一样,具体区别建议还是看看头文件比较好,这里我就多个事,顺手就贴出来了:
void* (*start_routine) (void*);
这样就缩小了两者之间的差异,剩下的事就只要把__type的地址传进去就可以了。由于使用的这样的实现,std::thread()创建一个新的线程可以接受任意的可调用对象类型(带参数或者不带参数),包括lambda表达式(带变量捕获或者不带),函数,函数对象,以及函数指针。
上面我们写了一个不带参数的demo,现在我们就创建包含参数和捕获的lambda表达式看看是否真的是这样,demo:
在启动了一个线程(创建了一个thread对象)之后,当这个线程结束的时候(std::terminate()),我们如何去回收线程所使用的资源呢?thread库给我们两种选择:1.加入式(join()) 2.分离式(detach())。值得一提的是,你必须在
thread对象销毁之前做出选择,这是因为线程可能在你加入或分离线程之前,就已经结束了,之后如果再去分离它,线程可能会在
thread对象销毁之后继续运行下去。
Note that you only have to make this decision before the std::thread object is destroyed—the thread itself may well have finished long before you join with it or detach it, and if you detach it,then
the thread may continue running long after the std::thread object is destroyed.-------《C++ Concurrency In Action》 2.1.1
join()字面意思是连接一个线程,意味着主动地等待线程的终止,上面的例子我都是使用了join()的方式。join()是这样工作的,在调用进程中join(),当新的线程终止时,join()会清理相关的资源(any storage associated with the thread),然后返回,调用线程再继续向下执行。正是由于join()清理了线程的相关资源,因而我们之前的thread对象与已销毁的线程就没有关系了,这意味着一个线程的对象每次你只能使用一次join(),当你调用的join()之后joinable()就将返回false了。光靠文字还是略显苍白的,肯定还是代码更加直观:
分离的线程,大致上是这样执行的,它运行结束后,不再需要通知调用它的线程:
线程的标识符
在thread类中有一个叫做_M_id的私有变量用来标识线程,其类型是std::thread::id,在GNU上实现如下:
of a non-executing thread”。与此同时,我们也可以在当前的线程中获取当前线程的线程标识符,方法比较简单直接调用std::this_thread::get_id()即可。
现在,我们写一个使用标准输出尝试输出线程id的demo:
关于何时用到std::thread::id::operator<,我暂时没有搞清楚,如果您知道,不妨告诉我,我将万分感激。
理解了以上内容,我们基本可以使用多线程去实现一些简单的任务了,当然要想安全地使用线程,这还是远远不够的。接下来我还要再探、三探thread库。
如若以上博文有错误、误导之处,请你原谅,还望批评指正,我在此先谢过各位。
相关文章推荐
- 用C++11 thread 类编写多线程程序
- 简单的基于libcurl和c++11 thread多线程的多线程下载程序
- [C++11 std::thread] 使用C++11 编写 Linux 多线程程序
- c++11 thread --多线程编译报错问题解决办法
- C++11 多线程 thread, lambda, CPU周期
- ubuntu升级C++11编写多线程程序
- C++之多线程(C++11 thread.h文件实现多线程)
- Windows下CodeBlocks配置 支持C++11 多线程 std::thread
- 使用 C++11 编写 Linux 多线程程序
- 如何使用 C++11 编写 Linux 多线程程序
- 使用 C++11 编写 Linux 多线程程序
- 使用 C++11 编写 Linux 多线程程序
- C++11多线程(二):std:thread
- 使用 C++11 编写 Linux 多线程程序
- c++11特性里的多线程thread的用法
- 使用 C++11 编写 Linux 多线程程序
- [C++11]并发程序模板(std::thread)
- C++之多线程(C++11 thread.h文件实现多线程)
- 《使用 C++11 编写 Linux 多线程程序(转载收藏)》
- Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序