Process & Thread
Process
Definition
- A process is an instance of a program running in a computer.
- A process is an independent unit of execution in a computer program, including the complete set of instructions and the associated memory and resources.
- It is a program that is under execution.
典型的进程定义有:
- 进程是程序的一次执行。
- 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
- 进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
Features
- 动态性 Dynamic:进程的实质是进程实体的一次执行过程,因此,动态性是进程的最基本的特征。动态性表现在“它由创建而产生,由调度而执行,由撤消而消亡”。可见,进程实体有一定的生命期。
- 并发性 Concurrency:多个进程实体同存于内存中,且能在一段时间内同时运行。
- 独立性 Independence:进程实体是一个能独立运行、独立分配资源和独立接受调度的基本单位。
- 异步性 Asynchronism:进程按各自独立的、不可预知的速度向前推进,或说进程实体按异步方式运行。
Components
进程实体 Process Entity包括:
- 程序块 Program Block: The code that is to be executed.
- 数据块 Data Block: The variables and data that are used by the program.
- 堆栈 Stack: The stack that is used to store the temporary data and function calls.
- 进程控制块 Process control block(PCB): It is a data structure that contains information about the process. It includes process state, process ID, CPU registers, CPU scheduling information, memory management information, and other information. It is used by the operating system to manage the process.
[[Ch2-1ProcessContorl#进程控制块 PCB]]
States
- 新建态 New: 进程已经创建,但未被 OS 接纳为可执行进程,并且程序还在辅存,PCB 在内存
- 就绪态 Ready: The process is ready to be executed.
- 运行态 Running: The process is currently being executed.
- 阻塞态 Blocked/等待态 Waiting: The process is waiting for some event to occur.
- 终止态 Exit: 因停止或取消,被 OS 从执行状态释放
当出现了引起进程挂起的事件时,用户请求将自己挂起,或者父进程请求挂起自己的子进程,这时使用挂起原语Suspend()
当发生激活事件后,系统利用激活原语Active()
将指定进程激活。激活原语将进程从外存调入内存,然后检查进程状态
挂起状态又称为静止状态,一个就绪进程被挂起,变为静止就绪;阻塞状态进程被挂起,称为静止阻塞。处于静止状态的进程保存在磁盘(外存)上,它只有被对换到内存才能被调度执行。
Note
- 即使进程等待的事件已经发生,只要进程处于挂起状态,它就不能执行。只有当进程从挂起状态恢复时,它才能根据自身的就绪条件(如等待的事件是否已经发生)决定是否可以执行。
- 使之挂起的进程可以为:自身、其父进程、OS
- 只有挂起它的进程才能使之由挂起状态转换为其他状态
Causes of Suspension
- 终端用户的请求。
- 父进程请求。
- 负荷调节的需要。当实时系统中的工作负荷较重,把一些不重要的进程挂起,以保证系统能正常运行。
- 操作系统的需要。操作系统有时希望挂起某些进程,以便检查运行中的资源使用情况或进行记账。
Blocked VS Suspend
阻塞:正在执行的进程由于发生某事件(如 I/O 请求、申请缓冲区失败等)暂时无法继续执行。此时引起进程调度,OS 把处理机分配给另一个就绪进程,而让受阻进程处于暂停状态,一般将这种状态称为阻塞状态。
挂起:由于系统和用户的需要引入了挂起的操作,进程被挂起意味着该进程处于静止状态。如果进程正在执行,它将暂停执行,若原本处于就绪状态,则该进程此时暂不接受调度。Same:
- 进程都暂停执行
- 进程都释放 CPU,即两个过程都会涉及上下文切换
Diff:
- 对系统资源占用不同:虽然都释放了 CPU,但阻塞的进程仍处于内存中,而挂起的进程通过“对换 Swapping”技术被换出(Swap Out)到外存(磁盘)中。
- 发生时机不同:阻塞一般在进程等待资源(IO 资源、信号量等)时发生;而挂起是由于用户和系统的需要,例如,终端用户需要暂停程序研究其执行情况或对其进行修改、OS 为了提高内存利用率需要将暂时不能运行的进程(处于就绪或阻塞队列的进程)调出到磁盘
- 恢复时机不同:阻塞要在等待的资源得到满足(例如获得了锁)后,才会进入就绪状态,等待被调度而执行;被挂起的进程由将其挂起的对象(如用户、系统)在时机符合时(调试结束、被调度进程选中需要重新执行)将其激活
Program vs Process: A program is a passive entity, such as a file containing a list of instructions stored on disk, whereas a process is an active entity, with a program counter specifying the next instruction to execute and a set of associated resources.
可执行程序和进程的区别
- 程序是永存的;进程是暂时的,是程序在数据集上的一次执行,有创建有撤销,存在是暂时的;
- 程序是静态的观念,进程是动态的观念;
- 进程具有并发性,而程序没有;
- 进程是竞争计算机资源的基本单位,程序不是。
- 进程和程序不是一一对应的:
- 一个程序可对应多个进程即多个进程可执行同一程序;
- 一个进程可以执行一个或几个程序。
Thread
Definition
- A thread is a basic unit of CPU utilization.
- It is a single sequence stream within a process.
- A thread is a lightweight process. It shares the same memory space and system resources with other threads in the same process.
也被称为轻量级进程,更加轻量。多个线程可以在同一个进程中同时执行,并且共享进程的资源比如内存空间、文件句柄、网络连接等。
[[Ch2-4Thread#线程概述]]
Features
- Lightweight: Threads are lightweight compared to processes. It takes less time to create and terminate threads.
- Shared resources: Threads in the same process share the same memory space and system resources.
- Efficiency: Threads are more efficient than processes because they share the same memory space and system resources.
Components
TCB Components
Tid: A unique thread identifier in the process.
同进程一样,每个线程也有一个线程 ID;进程 ID 在整个系统中是唯一的,线程 ID 只在它所属的进程环境中唯一
Register set: These are small storage areas that quickly hold and release data. They store intermediate values during execution.Including Program counter which keeps track of the execution of the thread, indicating the address of the next instruction to be executed.
Stack: It is a data structure that stores temporary data like function parameters, return addresses, and local variables.
States
同进程一样,线程之间也存在共享资源和相互合作的制约关系,致使线程在运行时也具有间断性。
线程运行时有以下 3 种状态:
- Running 执行状态:表示线程正获得 CPU 而运行;
- Ready 就绪状态:表示线程已具备了各种运行条件,一旦获得 CPU 便可执行;
- Blocked 阻塞状态:表示线程在运行中因某事件而受阻,处于暂停执行的状态;
Comparison
对比
线程具有许多传统进程所具有的特征,所以又称为轻型进程(Light-Weight Process) ,相应地把传统进程称为重型进程(Heavy-Weight Process),传统进程相当于只有一个线程的任务。
在引入了线程的操作系统中,通常一个进程都拥有若干个线程,至少也有一个线程。
下面从调度性、并发性、系统开销和拥有资源等方面对线程和进程进行比较。
- 调度 在传统的操作系统中,进程作为拥有资源和独立调度、分派的基本单位。而在引入线程的操作系统中,则把线程作为调度和分派的基本单位,而进程作为资源拥有的基本单位。
- 并发性 在引入线程的操作系统中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间亦可并发执行,使得操作系统具有更好的并发性,从而能更加有效地提高系统资源的利用率和系统的吞吐量。
- 拥有资源 一般而言,线程自己不拥有系统资源(也有一点必不可少的资源),但它可以访问其隶属进程的资源,即一个进程的代码段、数据段及所拥有的系统资源,如已打开的文件、I/O 设备等,可以供该进程中的所有线程所共享。
- 独立性 同一进程中的不同线程共享进程的内存空间和资源
- 系统开销 线程的切换只需要保存和设置少量的寄存器内容,不涉及存储器管理方面的操作。 由于一个进程中的多个线程具有相同的地址空间,在同步和通信的实现方面线程也比进程容易。在一些操作系统中,线程的切换、同步和通信都无须操作系统内核的干预。
- 支持多处理机系统 一个进程分为多个线程分配到多个处理机上并行执行,可加速进程的完成。
Linux Process/Thread Control Operations Comparison
应用功能 | 线程 | 进程 |
---|---|---|
创建 | pthread_create | fork,vfork |
退出 | pthread_exit | exit |
等待 | pthread_join | wait、waitpid |
取消/终止 | pthread_cancel | abort |
读取 ID | pthread_self() | getpid() |
同步互斥/通信机制 | 互斥锁、条件变量、读写锁 | 无名管道、有名管道、信号、消息队列、信号量、共享内存 |
Java Example
摘录自javaguide
从下图可以看出:一个进程中可以有多个线程,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间)资源,但是每个线程有自己的程序计数器、虚拟机栈 和 本地方法栈。
线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。
线程执行开销小,但不利于资源的管理和保护;而进程正相反。
有了进程为什么还需要线程?
进程切换是一个开销很大的操作,线程切换的成本较低。
线程更轻量,一个进程可以创建多个线程。
多个线程可以并发处理不同的任务,更有效地利用了多处理器和多核计算机。而进程只能在一个时间干一件事,如果在执行过程中遇到阻塞问题比如 IO 阻塞就会挂起直到结果返回。
同一进程内的线程共享内存和文件,因此它们之间相互通信无须调用内核。
为什么要使用多线程?
总体上
从计算机底层来说: 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
从当代互联网发展趋势来说: 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。
计算机底层
单核时代:在单核时代多线程主要是为了提高单进程利用 CPU 和 IO 系统的效率。 假设只运行了一个 Java 进程的情况,当我们请求 IO 的时候,如果 Java 进程中只有一个线程,此线程被 IO 阻塞则整个进程被阻塞。CPU 和 IO 设备只有一个在运行,那么可以简单地说系统整体效率只有 50%。当使用多线程的时候,一个线程被 IO 阻塞,其他线程还可以继续使用 CPU。从而提高了 Java 进程利用系统资源的整体效率。
多核时代: 多核时代多线程主要是为了提高进程利用多核 CPU 的能力。举个例子:假如我们要计算一个复杂的任务,我们只用一个线程的话,不论系统有几个 CPU 核心,都只会有一个 CPU 核心被利用到。而创建多个线程,这些线程可以被映射到底层多个 CPU 上执行,在任务中的多个线程没有资源竞争的情况下,任务执行的效率会有显著性的提高,约等于(单核时执行时间/CPU 核心数)。
Ref
teaching.csse.uwa.edu.au/units/CITS2002/lectures/lecture07/singlepage.html
Process & Thread