线程的前因后果,你了解吗?

进程最近有些烦恼,整日愁眉苦脸的,拜访内存的时候也有点心不在焉。算法

内存是个明眼人,开门见山的问道:“进程啊,最近遇到啥问题了?我看你最近情绪有点低落,有啥问题你就直接说出来嘛,我让你们伙儿来一块儿帮你想一想办法。”多线程

进程叹了口气,说道:“唉,最近不是说 CPU 单核频率到瓶颈了吗?人类就用多核芯来弥补单核处理器性能的不足,我们的 CPU 不也升级到四核了嘛。”函数

“是啊,这是好事啊,如今最多能并行处理 4 个进程,效率比之前高多了,这还很差吗?”内存疑惑的问。性能

“好是好,可我每次上 CPU 运行的时候,都忍不住去想,要是单核频率不增长,我总的运行的时间不仍是没有什么变化吗?之后的应用程序愈来愈大,愈来愈吃 CPU 资源,好比那些大型游戏进程,在短期内须要进行大量计算,靠单核撑不住怎么办。不谈之后,就说说我本身,我也想可以早点运行完,早点休息啊。”操作系统

tobe 注:很明显单进程的运行时间是变小了的,不过这里主要强调的是进程占用 CPU 的时间。线程

内存点点头,赞同道:“这个问题我却是没想到,多核处理器对单个进程确实不大友好。那咱得想办法让你可以同时使用几个核心。不过我一时间也想不到什么好办法,仍是和你们一块儿讨论下吧。”3d

在讨论会上,内存向你们说明了进程如今遇到的问题。blog

“一个进程怎么并行?”进程调度器第一个发出疑问:“我总不能把一个进程放在四个核上吧,这样不只毫无心义,还阻碍了其余进程的执行。”游戏

操做系统见多识广,说:“把进程一次放在几个核上运行确定是不可能的,我在想,我们的目标,其实就是让多个核心不冲突地帮助一个进程运行嘛。那咱们就得把进程「拆开」,而后放在几个核上。”进程

操做系统一边说,一边画了张图:

进程拆分

“大家看,假如说 fun1 和 fun2 这两个函数互不关联,咱们就可让两个核同时执行他们,这不就作到并行了吗?”

“你的意思是说把一个进程拆成好几个进程?”

操做系统摇摇头:“不是拆成多个进程,进程切换的代价太大了,再说了,这些拆出来的函数,他们是共用一个地址空间的,天生就可以数据共享,若是拆成进程,咱们还得再考虑进程之间的通讯问题,那多麻烦。不过为了跟进程区分,就叫他们「线程(Thread)」吧”

进程一惊,要把本身拆成线程?那本身不就没了?赶紧问道:“那我岂不是没有存在的余地了?”

进程调度器也慌了:“要是没了进程,我是否是也要被退休了?”

操做系统赶紧解释道:大家误会了,我要拆开的,是进程的执行流,进程不是包含了资源全部权执行流吗,资源全部权仍是由进程来把控,执行流就分给几个线程,就像这样:

执行流

tobe 注:在进程模型里,进程拥有对内存、I/O 通道、I/O 设备和文件等资源的控制权,称之为「资源全部权」。「执行流」能够看作进程在 CPU 上的执行过程(直观一点就是高级语言里的语句)。

进程恍然大悟:“也就是说我仍然是资源的掌控者,那些线程就至关于帮我干活的小弟?”

“没错,并且从这种角度看,你自己仍是一个单线程进程。”

听了这么久,内存发问了:“建立进程的时候,我要保存进程 PCB ,那为了建立线程,我是否是还得建立一个 TCB(Thread Control Block)?”

“固然了,线程切换须要的信息就得存在 TCB 里面。不过你放心,TCB 要比 PCB 小得多,因此线程切换会比进程切换快不少。”

多线程进程模型

你们听完,纷纷以为「线程」这个模型完美的解决了当前的问题,说道:“要不咱们如今就在操做系统里添上线程模型吧,早点解决进程的问题。”

可是操做系统面露难色,说:“线程模型只是咱们的一个假想,贸然加进来的话,可能会出问题,系统崩溃可就很差了,仍是要以稳定为主。。。但这个模型仍是得试的,要不咱们先建立一个线程库,靠一个用户级别的应用程序——线程调度器来管理这些线程吧。”

进程不解的问:“但是这样的话,我仍是被分配在一个单独的核心上啊,即便是多线程,也只能在单核上运行。再说了,若是这些线程里有一个被阻塞,在你看来,是整个进程阻塞了,那其余线程,即便是就绪态,也得不到 CPU 资源。”

操做系统仔细想了下,说:“没办法,用户级线程确实有这两个缺点,但相比起让内核来实现线程,用户级线程也有他的好处——线程切换不须要我进行状态转换(从用户态到内核态),开销小,除此以外,线程库能够有多个调度算法,可以为应用程序量身定作调度算法。”

tobe 注:有一种解决线程阻塞的方案叫 jacketing,他能够把一个产生阻塞的系统调用转化成一个非阻塞的系统调用,好比说,不直接调用系统级的 I/O 例程,而是让线程调用应用级的 I/O jacket 例程,这个 jacket 例程会检查 I/O 设备是否忙,若是忙的话,就不执行 I/O 操做,转而调度其余线程,避免了因等待 I/O 设备而形成的进程阻塞。


用户级线程很快投入使用,Linux系统中的 pthread(POSIX thread)库能够说是大获成功,操做系统作出了一项重大决定——支持内核级线程。

内核级线程解决了进程并行的问题,除此以外,因为内核看获得线程的存在,一个线程阻塞了,位于同一个进程中的其它线程仍然可以运行。

用户级线程和内核级线程

并行的问题解决了,进程表示本身十分开心。


但愿你在看完个人文章以后有所收获。

感谢你的阅读,咱们后会有期!

声明:原创文章,未经受权,禁止转载

相关文章
相关标签/搜索