一、前言
本文要介绍的是C++中的线程库thread
,当然,也并不仅仅只是介绍它,因为它只有简单的几个函数而已,很简单。
本文更多的是来讨论线程的必要性、底层原理、以及如何保证安全的使用它。
与之相对应的概念叫做进程,如果你不熟悉两者的区别,可以看一看本站的另一篇文章:进程与线程。
二、什么是线程?
如果到目前为止你还只是写过控制台程序的话,可能确实很难感受到线程的作用。
以最常见的微信为例,它是一个GUI
程序,即:带有界面。
那你思考过为什么无论它目前正在干什么(比如发送大文件、登录、发送消息等等),你都能很顺利的拖动、更换它的界面吗?
如果一个程序同一时间只是干一件事,比如发送一个100GB
的超大文件,可能得花费很长的时间对吧,那此时用户界面的响应怎么办呢?
这时如果当你拖动界面、更换聊天框等等操作,就会直接让程序暂停响应,因为它正在忙着发送文件。
不出意外的话,我相信你应该是遇到过这些情况的。
一般来说,GUI程序最重要的就是与用户的交互性,无论程序当前在干什么,用户应该都能实时看到、并对其做出控制,所以基本所有GUI程序的主线程都是用来处理用户界面交互的。
这里的主线程,就是当你启动一个程序时,自带的那个执行代码的线程。
注意:进程本身是不执行代码的,执行代码的是线程。
一个进程可以理解为一个exe
程序(并不绝对),而一个进程中可以有很多个线程,其中默认启动的执行代码的线程一般就叫做主线程。
而至于其它的任务,比如最直观的例子:发送文件,则是交给了其它线程来做,主线程在这一过程只做两件事:
- 将发送文件的任务交给其它线程。
- 如果其它线程在处理过程中发生了什么情况,再反应给主线程,由主线程来决定接下来该怎么做
比如子线程在发送文件时网络出错,就会报告给主线程,再由主线程决定是否将其显示到用户界面上。
注意在一般情况下,为了保证安全性,只会有一个线程来处理用户界面交互,而这个线程一般就是主线程,至少就我目前看到的GUI框架都是这样做的,比如Qt
、MFC
都是如此。
上面用的一个微信GUI程序发送大文件、同时需要处理用户点击、拖动等情况的例子作为讲解,将其更直观的反应到代码中就是下面这样:
当然,上面的也仅仅只是一个示例代码程序,并不存在这些函数,但一个GUI程序的运行流程都大致如此,只是细节不同罢了。