线程引入原因
-
性能
操作系统开销大;
Unix的轻型进程(fork) -
应用
进程代码并发执行的需求;
例子:PPT编辑(输入/拼写检查/存盘) -
硬件
多核处理器;
加速进程的运行
线程
线程
- 可在CPU上运行的基本执行单位
- 进程内的一个代码片段可以被创建称为一个线程
- 线程状态:就绪、运行、等待等
- 线程操作:创建、撤销、等待、唤醒等
- 进程依旧是资源分配的基本单位
- 线程自己不拥有系统资源,通过进程申请资源
传统进程
- 重型进程
- 只有一个线程:主线程
- 单线程模型
进程和线程
方面 | 进程 | 线程 |
---|---|---|
代码 | 进程包含线程 | 线程是进程中的一段代码 |
资源 | 进程是资源分配基本单位 | 线程不拥有资源,共享使用进程的资源 |
调度 | 同一进程中的线程切换不会引起进程切换 | 线程是基本调度单位 |
切换 | 重量级上下文切换,代价大 | 轻量级切换,代价小 |
生命期 | 进程撤销会导致它的所有线程被撤销 | 线程撤销不会影响进程 |
线程结构
- 代码和数据:来自进程
- 各类资源:来自进程
- 线程控制块(TCB)
包含线程ID,程序计数器PC,寄存器集,栈空间
Windows线程:
单线程和多线程
单线程:
一个进程只有一个线程;
早期操作系统
多线程:
一个进程有多个线程;
支持线程的操作系统
线程优点
- 响应度高
线程创建开销小;
例子:web服务器 - 资源共享
进程中的线程可以共享进程资源 - 经济性
线程创建、上下文切换比进程快;
Solaris:创建线程比进程快30倍,线程切换比进程切换快5倍 - MP体系结构的运用
一个进程中的线程在不同处理器上并行运行
Web服务器
Windows线程
- 操作系统支持线程
- 线程主要数据结构:
(1)执行线程块ETHREAD
Executive thread block
对应程序地址
指向KTHREAD指针
内核空间
(2)核心线程块KTHREAD
Kernel thread block
线程调度和同步信息
内核空间
(3)线程环境块TEB
Thread environment block
用户空间的数据结构,线程本地存储
Linux 线程
- Linux 2.2版引入线程
- 通过clone() 系统调用创建线程
类似fork
Linux只支持克隆线程 - 用术语“任务”表示进程和线程,一般不用“线程”
- 用户线程:PThreads
Clone
- 创建进程或者线程
- Clone可有选择继承父进程的资源
不和父进程共享
int clone(int (\*fn)(void *),void *child_stack, int flags, void *arg)
fn:函数指针,指向一个函数体,即想要创建进程的静态程序
child_stack:给子进程分配系统堆栈的指针
flags:要复制资源的标志,描述从父进程继承的资源
多线程模型
用户(管理)线程
用户线程:由用户线程库进行管理的线程
- 内核看不到用户线程
- 用户线程的创建和调度在用户空间内,不需要内核的干预
- 应用于传统的只支持进程的操作系统
例子:
- POSIX Pthreads
- Win32 threads
- Java threads
内核(管理)线程
内核线程:内核进行管理的线程
- 需要内核支持
- 由内核完成线程调度
- 由内核进行创建和撤销
例子:Windows XP/2000,Solaris,Linux,Tru64 UNIX,Mac OS X