洪典松
线程与进程,如兄如父如homie?
来源:侯振峰     发布时间: 2019-04-25      浏览次数:55

字号:

显然这是一个在面试中的高频问题,每次碰上,第一反应都是欣喜,心想这题我见过,进程就是一个程序嘛,可以由一个或多个线程组成。然后和面试官尴尬对视三十秒,七零八落说一通,脑海里很多想法,却没法有条理的串在一起,自己也觉得不满意。还是沉下心,好好整理一下。

 

 

在此之前,先明白几个概念。

 并行与并发:

并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。

上下文切换

即使是单核CPU也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程时同时执行的,时间片一般是几十毫秒(ms)。

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再次加载这个任务的状态,从任务保存到再加载的过程就是一次上下文切换

 

一、个人定义

教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”,但是理解起来还是抽象。

首先想一想,他俩是因为什么出现并‘’狼狈为奸‘’的。

进程的出现是为了更好的利用CPU资源使到并发成为可能。

线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。

他们的终极目标都是为了进一步提高cpu的利用率,类比于内存与缓存。

二、具体差异

1,拥有系统资源的差异:

每个进程都拥有自己独立的内存空间,但是同一个进程内部的不同线程间是内存共享的,线程不拥有系统资源,只拥有运行中必不可少的信息(如一组寄存器、堆栈和程序计数器)。由此拥有系统资源的根本性差别,产生了几个子区别:

可靠性差异:进程更加稳定,一个进程崩溃,其余不受影响,因为其内存空间是独立的。但是一个子线程崩溃,拥有它的整个进程都崩溃了。通信方式差异:每个进程有自己的地址空间。两个进程中的地址即使值相同,实际指向的位置也不同。进程间通信(IPC)一般通过操作系统的公共区进行,是系统调用,如管道pipe、信号signal、共享内存shared memory、信号量semophore。同一进程中的线程因属同一地址空间,可直接通信(不必通过操作系统(内核)调度)。

2,上下文切换的差异:

原则上讲,一个CPU只能分配给一个进程,要实现多任务,就必须要使用并发技术。通过cpu时间片轮转进程调度算法,完成多任务。(线程中,多线程的实现也和进程同理),在时间片轮转调度过程中,线程进程差异化从上下文切换环节上表现出来。

进程上下文切换包括三步。a.切换页目录以及使用新的地址空间。b.切换内核线。c.切换硬件上下文。

而对于线程来讲,由于是共享内存空间(好像根本原因又回到了第一点),第一步是不需要的。只要bc就能完成上下文切换,节省了大量的损耗。

 

一直想把他们抽象的关系找到生活里的映射,无奈实在找不到如此完美的模型。

起源上,进程是爹,有时计划生育,有时野性繁殖。线程们兄弟情深,一人失恋,剩下的也悲痛欲绝,怎么也理解不了父辈之间的冷漠交情,其实道理也简单,兄弟们都生活在一个大house里,相依为gay,聊起天来也方便,感情自然铁。

直到有一天他们爱上了一个同一个小姑娘,大哥把人约到了家里,拉小姑娘进小房间里锁门谈心,弟弟们门外排队等候,虽然迫不及待,但也恪守交规,二弟排在第一位,每隔几秒就去检查门开了没有。。。

再写就变态了,到此为止!

 

最后贴一个:

http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

来自阮一峰的博客,将CPU,线程,进程分别类比于工厂和其中的车间和工人,有一点点瑕疵但是很深动。

1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。

2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。(这句话没有问题,但是这里没有解释单cpu处理多任务的情况,需要完善)

3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。

4.一个车间里,可以有很多工人。他们协同完成一个任务。

5.线程就好比车间里的工人。一个进程可以包括多个线程。

6.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。(前提是在一个进程里的每一个线程)

7.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

8.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。

9.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。

10.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。

不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。(既然讲到互斥锁,其实还可以具体化一下偏向锁和轻量级锁)

11.操作系统的设计归结为三点:

(1)以多进程形式,允许多个任务同时运行;

(2)以多线程形式,允许单个任务分成不同的部分运行;

(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

 

 

 参考的博客:

1.https://www.cnblogs.com/xh0102/p/5710074.html   通信方式的区别

2.https://blog.csdn.net/bxw1992/article/details/78115860  上下文的区别

3.https://www.jianshu.com/p/f11724034d50 不错的定义

4.http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html  有趣的类比

5.https://www.zhihu.com/question/25532384  独特的概括,膜拜

 

  • 相关内容: