后端面试必问题:进程与线程的区别里藏着这么多关键细节

相信大家对进程与线程都有所了解,那么假设在面试中被问到 “进程与线程的区别”,我们应该如何回答呢?

【详细回答】

在操作系统的范畴内,进程是具备独立功能的程序在特定数据集合上的运行过程,同时它也是系统进行资源分配和调度的基本独立单元。

进程拥有一系列显著特点,这些特点深刻地反映了其在操作系统中的运行机制与本质属性:

  1. 动态性:进程并非一成不变,而是从被创建的那一刻起,就踏上了其独特的生命周期旅程,直至最终消亡。这一过程涵盖了进程的启动、执行各种任务以及在任务完成或遇到异常时的结束,其状态始终处于动态变化之中。
  2. 并发性:当多个进程并发执行时,会展现出三个独特的特性:
    • 间断性:并发进程在运行过程中具有间断运行的特点。尤其是当多个进程需要协同完成同一任务时,它们之间往往需要进行同步等操作,这就不可避免地导致进程在某些时刻会暂停执行,等待其他进程的配合或系统资源的分配。
    • 失去封闭性:由于并发进程共享系统中的各类资源,这就使得任意一个进程对共享资源状态的改变,都可能对其他进程产生影响。这种失去封闭性的特性,使得进程的执行结果不再仅仅取决于自身的代码逻辑,还与其他并发进程的执行顺序和速度密切相关。这进一步导致了进程执行的不可再现性,即便是在相同的初始环境和条件下,每次执行的结果也可能不尽相同。可以说,正是失去封闭性这一特性,直接引发了进程执行的不可再现性。
    • 不可再现性:如前所述,在相同的初始环境和条件下,并发执行的进程由于受到其他进程的干扰以及资源竞争等因素的影响,可能会得到不同的执行结果。这也是并发环境下进程管理面临的一大挑战。
  3. 独立性:进程能够独立运行,并且是系统进行资源分配时的最小单位。每个进程所获得的资源,如内存空间、I/O通道、I/O设备等,都独立于其他进程,这确保了进程在运行过程中的自主性和稳定性。
  4. 异步性:进程的推进状态是不可预知的,它们以各自独立的速度和顺序向前执行。这种异步性是由进程的并发性所导致的,因为在多进程环境下,操作系统会根据各种调度算法来分配CPU时间片,使得进程的执行顺序和时间具有不确定性。不过,通过合理运用同步与互斥机制,可以在这种异步性的前提下,保证进程能够得到确定且可再现的执行结果。

在尚未引入线程概念之前,进程具有两个关键特性:

  • 资源所有权最小单位:这意味着一个进程对其所拥有的资源,包括内存、I/O通道、I/O设备等,具有完全的控制和所有权。进程在运行过程中,可以根据自身的需求对这些资源进行分配、使用和管理。
  • 调度/执行的最小单位:进程作为一个独立的实体,能够被操作系统内核进行调度。内核会根据一定的调度策略,将CPU时间片分配给不同的进程,从而实现多个进程的并发执行。

而“线程”的出现,可以看作是在调度/执行这一属性上对进程的进一步细化。在引入线程之前,进程是操作系统调度的最小单位;而当引入了由操作系统内核支持的线程(即内核级线程)后,线程便取代进程成为了操作系统调度的最小单位。

引入线程为操作系统和应用程序带来了诸多显著优势:

  1. 进一步提高并发性:在单处理机系统中,线程模型能够将同一个进程内的CPU计算和I/O访问分离开来,使得它们可以并发执行,从而提高了系统资源的利用率。在多处理机系统中,引入线程模型后,每个内核级线程都能够独立占用一个处理机,充分发挥了多处理机系统并行处理的优势,极大地提升了系统的整体性能。
  2. 共享地址空间与可用数据:线程之间可以直接共享数据,无需通过操作系统内核进行繁琐的数据传递。这种直接共享数据的方式,大大提高了数据传输的效率,在速度上相较于进程间的数据共享具有明显的优势。
  3. 更轻量级:在许多操作系统中,创建一个线程的速度比创建一个进程要快10至100倍。不仅如此,线程的切换和撤销操作也远比进程要迅速得多。这使得线程在频繁创建和销毁的场景下,能够显著降低系统开销,提高系统的响应速度。
  4. 更好的交互性:在线程模型的支持下,图形界面程序能够更加流畅地响应用户的操作。线程可以将耗时的计算任务与界面交互任务分离,避免因长时间的计算操作导致程序“卡死”,从而为用户提供更加良好的交互体验。

【知识拓展】

线程在操作系统中的实现方式主要可划分为两大类别,分别是内核级线程(Kernel Supported Threads,KST)以及用户级线程(User-Level Threads,ULT) ,它们在实现机制、调度方式等方面存在显著差异。

  1. 用户级线程:这种线程的管理工作完全由应用程序自身负责,并且所有操作均在用户空间内完成。这就意味着,操作系统内核层面对于用户级线程的存在是“无感知”的。在用户级线程的运行模式下,从操作系统的调度视角来看,系统调度的最小单位依旧是进程。而线程在进程内部的调度工作,则由其所属的进程来执行。这就好比一个大工厂(进程)里面有多个小车间(用户级线程),工厂的整体运营规划(系统调度)是以工厂为单位进行的,而各个车间内部的工作安排(线程调度)则由工厂内部自行决定 。这种实现方式的优点在于线程的创建、切换等操作不需要陷入内核态,开销较小,效率较高;但缺点也很明显,一旦进程中的某个线程阻塞,整个进程都会被阻塞,因为操作系统只知道进程的状态,无法单独调度线程。
  2. 内核级线程:与用户级线程不同,内核级线程的实现离不开操作系统内核的支持。从线程的创建、阻塞,到撤销以及切换等一系列关键操作,均是在内核空间中完成的。内核通过一种被称为TCB(线程控制块)的机制,对线程进行全面的感知与精准控制。在这种实现方式下,线程已然成为系统调度的最小单位。这就像是每个车间(内核级线程)都直接与工厂的管理核心(操作系统内核)建立了联系,工厂的管理核心可以直接对每个车间进行任务分配和调度。这种方式的好处是,当某个线程阻塞时,其他线程仍可继续运行,提高了系统的并发性能;但由于涉及到内核态的操作,线程的创建、切换等开销相对较大 。