线程基础
线程(Thread):有时被称为轻量级进程(Lightweight Process,LWP),是程序执行最小单位。
线程组成:线程ID、当前指令指针(PC)、寄存器集合、堆栈
通常意义上,一个进程由一个到多个线程组成,各个线程之间共享程序的内存空间(包括代码段、数据段、堆等)及一些进程及的资源(如打开的文件信号)。一个经典的线程和进程关系图如下所示:
使用多线程的必要性
- 单线程等待时无法充分利用资源,如等待网络响应
- 单线程阻塞会中断交互
- 程序本身需要多并发,如多终端下载软件(Bittorrent)
- 发挥多核CPU的性能
- 多线程再数据共享方面效率高很多
线程的访问权限
线程的访问非常自由,可以访问进程内存里的所有数据,甚至包括其他线程的数据(如果它知道其他线程的堆栈地址),实际运用中线程也拥有自己的私有存储空间,包括:
- 栈(尽管并非完全无法被其他线程访问,一般情况下认为是线程私有的数据)
- 线程局部存储(Thread Local Storage)
- 寄存器(包括PC寄存器)
从C程序员的角度看,数据在线程间是否私有如下所示:
线程私有 | 线程间共享(进程所有) |
---|---|
局部变量 | 全局变量 |
函数参数 | 堆上的数据 |
TLS数据 | 静态变量 |
程序代码 | |
打开的文件 |
线程调度与优先级
- IO密集型线程(IO Bound Thread):I/O操作频繁,频繁等待的线程
- CPU密集型线程(CPU Bound Thread):CPU操作频繁,经常把时间片耗尽的线程
线程通过下列方式变更优先级:
- 用户手动更改
- 根据等待状态的频繁程度被优先级,IO密集型线程更容易得到优先级的提升
- 长时间得不到执行而被提升,防止饿死
可抢占线程和不可抢占线程(现在不可抢占线程已经很少见)
- 可抢占线程:线程用尽时间片后,会被剥夺继续执行的权利,而进入就绪状态
- 不可抢占线程:知道主动放弃或等待某事件(如I/O等)