注意这个题目问的是进程切换与线程切换的区别,不是进程与线程的区别。当然这里的线程指的是同一个进程中的线程。

这个问题能很好的考察面试者对进程和线程的理解深度,有比较高的区分度。

要想正确回答这个问题,面试者需要理解虚拟内存。

虚拟内存解放生产力

对于程序员来说,我们在编程时实际上是不怎么操心内存问题的,对于使用Java、Python、JavaScript等类型语言的程序员来说更是如此,自动内存回收机制的引入使得使用这类语言的程序员几乎完全不用关心内存问题;即使对于编译型语言C/C++来说,程序员需要关心的也仅仅是内存的申请和释放。

总的来说,作为程序员(无论使用什么类型的语言)我们根本就不关心数据以及程序被放在了物理内存的哪个位置上(设计实现操作系统的程序员除外),我们可以简单的认为我们的程序独占内存,比如在32位系统下我们的进程占用的内存空间为4G;并且我们可以申请超过物理内存大小的空间,比如在只有256MB的系统上程序员可以申请1G大小的内存空间,这种假设极大的解放了程序员的生产力。

而这种假设实现的背后功臣就是虚拟内存。

什么是虚拟内存

虚拟内存是操作系统为每个进程提供的一种抽象,每个进程都有属于自己的、私有的、地址连续的虚拟内存,当然我们知道最终进程的数据及代码必然要放到物理内存上,那么必须有某种机制能记住虚拟地址空间中的某个数据被放到了哪个物理内存地址上,这就是所谓的地址空间映射,也就是虚拟内存地址与物理内存地址的映射关系,那么操作系统是如何记住这种映射关系的呢,答案就是页表,页表中记录了虚拟内存地址到物理内存地址的映射关系。有了页表就可以将虚拟地址转换为物理内存地址了,这种机制就是虚拟内存。

每个进程都有自己的虚拟地址空间,进程内的所有线程共享进程的虚拟地址空间。

现在我们就可以来回答这个面试题了。

进程切换与线程切换的区别

进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。

举一个不太恰当的例子,线程切换就好比你从主卧走到次卧,反正主卧和次卧都在同一个房子中(虚拟地址空间),因此你无需换鞋子、换衣服等等。但是进程切换就不一样了,进程切换就好比从你家到别人家,这是两个不同的房子(不同的虚拟地址空间),出发时要换好衣服、鞋子等等,到别人家后还要再换鞋子等等。

因此我们可以形象的认为线程是处在同一个屋檐下的,这里的屋檐就是虚拟地址空间,因此线程间切换无需虚拟地址空间的切换;而进程则不同,两个不同进程位于不同的屋檐下,即进程位于不同的虚拟地址空间,因此进程切换涉及到虚拟地址空间的切换,这也是为什么进程切换要比线程切换慢的原因。

有的同学可能还是不太明白,为什么虚拟地址空间切换会比较耗时呢?
这也是面试官紧接会问的第二个问题。
关于这个问题的答案,关注公众号“码农的荒岛求生”并回复“地址切换”几个字你就能得到答案啦。

总结

虚拟内存是现代操作系统极其重要的一部分,当然在这里限于篇幅我们只能简单介绍,关于虚拟内存的详细讲解请参见这里《深入理解操作系统