进程与线程
简单来说,一个进程就是一个正在执行程序的实例,它有存放程序正文和数据以及其他资源的地址空间。这些资源中包括打开的文件、子进程、即将发生的报警、信号处理程序、帐户信息等。而线程类似于一个迷你进程,线程是进程中活动的主体,之所以说它迷你,是因为它本身并不集中资源,一个进程中的所有资源被它的所有线程共享,它们具有共享同一个地址空间和所有可用数据的能力。可以想像一下,有这样一个工厂,里面有各种制造某种产品的原材料(资源),有制造某种产品的说明书(程序正文),且有一定数量的工人(线程)(这样说明也许不是很准确,因为对于某些不支持多线程的操作系统,进程才是调度的主体)。
也许会奇怪,有了进程,不就可以实现多道程序设计了吗?毕竟系统可以切换执行不同的进程。那为什么还要引进线程这个概念呢?
第一个,很简单,有时候我们需要共享同一个地址空间和所有可用数据的能力。前面说过了,线程具有这种能力,但是每个进程都是隔离开来的,它们具有不同的地址空间。之所以可以让线程拥有这种能力,是因为线程是属于同一个用户进程中的,是可以信赖的,而且线程通常都是为完成同一个目标而工作的。
第二个,前面还说过线程是迷你的进程,由于它比进程更轻量级,所以它们比进程更容易创建(想下上面的例子,重建个工厂比多请个人难得多吧),尤其是用户级线程来说,同一个进程间的线程的切换不需要陷阱,不需要上下文切换,也不需要对内存高速缓存和TLB进行刷新。同样也更容易撤销。
第三个理由是基于性能方面的考虑。若多个线程都是CPU密集型的,那么并不能获得性能上的增加,但是如果存在着大里的计算和大量的I/0处理,拥有多个纯种允许这些活动重叠进行从而会加快应用程序执行的速度。这样的话进程中的一个线程被阻塞时就不会导致整个进程被挂起,因为还有别的线程可执行。再想下上面的例子,假如工厂只有一个工人,那么他在生产一件产品时,只能等待它完成后才去生产另一件。那假如有两个工人的话,就可以同时进行生产,效率也就提高了。当然也不能说越多工人也好,毕竟一个工厂需要的员工数是一定的,不然就会造成资源浪费。进程里面的线程数也是一样,毕竟每个线程需要空间来保存自己的程序计数器,寄存器的值等。且它们也都拥有自己的栈空间,这是供各个被调用但是还没有从中返回的过程使用的。
很多人也许会混淆进程跟线程的使用情况。想像一下一个工厂里面有两条流水线,相当于两个进程,可以同时制造两种产品。但是流水线又分为不同的部分,可以想像成每个部分为一个线程,每个部分可以并行运行,但都是为了完成同一个目标而已工作的。也就是说,操作系统会创建不同的进程来处理不同的作业,但是假如作业里面又有CPU计算跟I/O处理,就可以创建两个线程来分别进行CPU计算跟I/O处理,这样就大大缩减了作业的运行时间。
其实说到底,尽管线程必须在某个进程中执行,但是要清楚线程跟它的进程是不同的概念的,并且可以分别处理。进程用于把资源集中在一起,而线程则是在CPU上被调度执行的实体(类似于前面的工厂与工人的概念,工厂拥有各种资源,但实际上进行工作的是工人)。但线程又具有进程的某些性质,如多个线程共享同一个地址空间和其他资源,而多个进程共享物理内存、磁盘、打印机和其他资源。所以线程有时又被称为轻量级进程。