目录
进程是一个正在执行的程序, 该程序是可以控制线程的。 单个进程中可以包含多个控制线程的功能。
进程是:
- 资源分配单位;
- 调度(调度)单元。
传统上,进程只有一个控制线程。
如果我们将上述两个概念分开,并允许在一个进程中有多个控制线程,我们就得到了线程。也就是说,进程被用来将资源分组在一起;线程是被调度(计划) dispatched(scheduled) 在CPU上执行的实体。
概述
线程是现代操作系统中CPU利用率的基本单位。也称为轻量级进程lightweightprocess(LWP). 。它由线程 ID、程序计数器、寄存器集合和栈组成。
传统的进程只能控制单个线程。 现代的进程可以控制多个线程,意味着可以同时做多个任务。
多线程:
- 允许在同一进程中有多个线程。
- 同一个进程中的两个线程之间可以共享代码段、数据段和其他操作系统资源,如打开文件和信号。
- 但是,一个进程中的每个线程都有一个私有线程Context(包括CPU寄存器集和其他状态信息)和一个私有堆栈。
- 是进程的一个实体;
- 是被系统独立调度和分派的基本单位;
- 自己基本不拥有资源,只拥有在运行过程中必不可少的资源(e.g. 程序计数器、寄存器、栈);
- 可与同属于一个进程的其他线程共享进程所拥有的资源;
- 可以创建和撤销另一个线程;
- 同一进程中的多个线程可以并发执行;
- 一个进程一般拥有若干线程,至少需要一个线程;
- 进程不再是一个可执行的实体。
单线程进程和多线程进程的对比图:
一个应用程序是被独立进程控制多个线程来实现的。
现代的许多操作系统都是多线程的,少数线程在内核中运行,每个线程完成一个指定的任务,如管理设备或中断处理。
线程的优点
- 响应度高:多线程即使其部分阻塞或执行较冗长的操作,该程序仍能继续执行,从而增加了对用户的响应程度。
- 资源共享:由于同一进程中的线程默认共享内存和资源,因此它们可以彼此通信,而无需调用内核。
- 经济:创建新线程所需的时间和资源要比创建进程少得多。在同一进程中Context 切换线程所需的时间要少得多。所以创建和切换线程会更经济。
- 多处理器体系结构的利用:不管有多少CPU,单线程进程只能运行在一个CPU上。通过为每个CPU分配一个多线程,可以实现并行。
多线程模型
- 用户线程:接受内核支持,而无须内核管理,属于用户层的线程
- 内核线程:由操作系统直接支持和管理
用户线程
它在内核之外实现,作为用户空间中的线程库。它是为线程创建、调度和管理提供支持的库。就内核而言,它是管理普通的单线程进程。例子:Mach C-threads Solaris 2 UI-threads
用户线程的优点。
- 线程管理和上下文切换不需要困在内核中。这将节省许多CPU周期。
- 允许每个进程有自己的自定义调度算法。
用户线程的缺点
- 执行阻塞系统调用的任何用户级线程都会导致整个进程阻塞。即使其他线程已经准备好在进程中运行。
- 在具有多处理器的系统上,用户级的线程不能被分派并行执行。
内核线程
- 它直接由操作系统支持。内核在内核空间中执行线程创建、调度和管理。例子Windows NT / XP Solaris
现代操作系统都支持内核进程。
用户线程和内核线程之间存在三种关系:
- 多对一模型;将许多用户级线程映射到一个内核线程; 线程管理是由线程库在用户空间进行的,效率比较高;但是如果有一个线程执行了阻塞系统调用,那么整个进程会阻塞,因为在任意时刻只有一个线程能访问内核,多个线程不能并行运行在多处理器上
- 一对一模型;将每个用户线程映射到一个内核线程; 在某个线程阻塞时,能允许另一个线程继续执行;能允许多个线程能并行运行在多处理器系统上; 缺点是每创建一个用户线程就需要创建一个相应的内核线程
- 多对多模型:多路复用了许多用户线程到同样数量或更小数量的内核线程上;是上两种的优化;可以创建任意多的用户线程,并且相应内核线程能在多处理器系统上并发执行,而且当一个线程执行阻塞系统调用时,内核能调度另一个线程来执行
线程库
- 为程序员提供创建和管理线程的API
实现线程库有两种方法:
- 第一种方法:在用户空间中提供一个没有内核支持的库,此库的所有代码和数据结构都存在于用户空间,调用库中的一个函数只是导致了用户空间中的一个本地函数调用,而不是系统调用;
- 第二种方法:执行一个由操作系统直接支持的内核级的库,此时,库的代码和数据结构存在于内核空间中,调用库中的一个API函数通常会导致对内核的系统调用
目前主要三种线程库:POSIXPthread Win32 Java
线程取消
- 线程取消:在线程完成之前终止线程的任务;
要取消的线程通常称为目标线程。目标线程的取消可在如下两种情况下发生:
- 异步取消:一个线程立即终止目标线程;
- 延迟取消:目标线程不断地检查它是否应该终止,这允许目标线程有机会以有序的方式来终止自己
线程池
线程池的主要思想是:
- 在进程开始时创建一定数量的线程, 并放入到池中以等待工作。当服务器收到请求时, 它会唤醒池中的一个线程(如果有,并且可以用的线程),并将要处理的请求传递给它。一旦线程完成了服务,它会返回到池中再等待工作。如果池中没有可用的线程,那么服务器会一直等待直到有空线程为止。
线程池具有如下主要优点:
- 通常用现有线程处理请求要比等待创建新的线程要快。
- 线程池限制了在任何时候可用线程的数量。这对那些不能支持大量井发线程的系统非常重要。
线程池中的线程数量由系统CPU 的数量、物理内存的大小和并发客户请求的期望值等因素决定。
线程特定数据
同属一个进程的线程共享进程数据。有些情况下每个线程可能需要一定数据的自己的拷贝,这种数据称为线程特定数据。