目录
-
-
- 走进线程
-
- 多进程编程和多线程编程
- 从hello world开始
-
- 启动线程
- 传入参数
- 总结
-
走进线程
最近狂喊的 AMD YES,就是一个极强的线程撕裂者。推出的移动端CPU都已经达到了8核16线程,但是很多应用对多线程优化不好,导致多核性能更强的AMD在有的方面还不如牙膏厂-Intel。如何提升多线程编程能力,就需要大量积累。尤其是在服务器编程方面,我们实验室购置的服务器都是48核了,如果还是依靠单线程那就显得太low了。
多进程编程和多线程编程
多进程编程和多钱程编程,都可以使用并行机制来提升系统的运行效率。二者的区别在于运行时所占的内存分布不同,
多钱程是共用一套内存的代码块区间;而多进程是各用一套独立的内存区间。但是多进程的缺点就是创建一个进程成本很高,而且系统对进程数量有限制,不允许无限制的增长。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZj91YpB3IwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPJR1T0kleONTRq1ENj1mYsJlMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1cDOzIzM0UTMwIjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
多线程编程的优点是效率较高一些,适用于批处理任务等功能;不足之处在于,任何一个线程崩溃都可能造成整个进程的崩溃,因为它们共享了进程的内存资源池。
学习多线程必须了解操作系统中,关于互斥的有关内容。
从hello world开始
namespace dyj01 {
int i = 0;
void hello() {
std::cout << "hello world : " << ++i << endl;
}
void test() {
std::thread t_1( hello );
std::thread t_2( hello );
t_1.join();
t_2.join();
}
} // namespace dyj01
使用关键字
thread
声明线程,然后传入需要进行多线程的函数名称即可。
C++有一个特点就是解析语法,任何能够解析为声明的都要被解析为声明。
std::thread my_thread(back_task());
这就会导致C++解析为一个函数的声明。解决办法是加上一个小括号或者使用大括号,其中小括号是声明这不是一个类型,避免被解析为声明;而大括号是强制不允许转换。
这里传入的函数可以一下几种类型:
- lambda表达式:
[](int x) { cout << x << endl; }
- 普通函数
- 成员函数
启动线程
可以显示使用两种方式启动线程:
-
:主线程等待子线程结束之后才可以结束(结合)join()
-
:主线程不在与子线程一致,子线程可以自动执行(分离)detach()
但是在线程开始之后没有进行
join()
和
detach()
调用会出现意外,所以我们可以采用RAII的资源管理方法对线程进行管理。而且一旦调用过一次
join()
或者
detach()
就不能再次调用了,所以可以调用
joinable()
函数判断是否可以调用
join()
和
detach()
。
if(t.joinable())
t.join();
传入参数
线程可以启动了,但是对于一些需要传参的函数来说这样是不能正确执行的,所以在定义多线程是可以传入参数。
thread t1(fun, x);
其中x就是传入的参数值。
但是所有线程传入的值都是pass-by-value,如果需要传入引用则需要调用std中的ref函数来进行包装。
thread t1(fun, ref(x));
此时传入的x就是一个引用了。
在C++11中引入了多线程,一起来的还有右值引用。对于多线程来说
thread
实例是只可以移动不可以复制的,所以如果我们需要转移线程的所有权必须使用右值引用,比如
thread t1(fun); // t1拥有线程所有权
thread t2(move(t1)); // 通过移动构造函数将线程所有权转移到了t2
thread t3 = t2; // 通过移动赋值函数将线程所有权转移到t3
如果此时再给
t3
赋值一个别的线程,那么原有的线程就会被终结。
那么如何来验证上面这个例子呢,就需要知道每个线程的线程号,这相当于你的身份证一样是唯一的。我们就来看一下上述的这个结论是否正确吧。
确实这三个实例的线程号是相同的,并且可以主线程还有专门的一个标识,如果是执行主线程那么执行结果会不一致,
master_thread
总结
C++在其他语言都推出多线程很久之后,才推出自己的多线程。*而且很多人会考虑一个问题就是既然多线程是一个实例,可不可以放到容器中呢?*答案是当然可以,而且在后面线程池部分全靠线程容器来实现的。这是多线程的第一部分,应该后面还有6章左右,这也是我的一个总结,也希望能够帮助到别人,谢谢!