操作系统:线程的基本概念

线程是操作系统调度的基本单位,它可以视为进程的一个控制流。一个进程包含1个到多个线性,进程的第一个线程随着进程的启动而创建,也就是进程的主线程。线程无法独立于进程存在。
每个线程拥有自己的线程栈,用于存储自己的私有数据。线程之间共享进程的许多资源,包括代码段、数据段、堆、信号处理函数、进程已经打开的文件描述符表等等。
一、线程的描述符(TCB)
线程控制块(TCB)也即线程描述符
 
字段
说明
线程ID(TID)
线程唯一标识符
栈指针
指向线程自己的栈
程序计数器
指向线程的当前程序指令
线程状态
运行,准备,等待,开始,完成
寄存器值
线程的寄存器值
PCB指针
指向线程所属进程的PCB
 
每个线程拥有自己的标识,成为线程ID或者TID。理论上TID只需在所属进程范围内唯一即可,不过实际Linux系统在系统范围内保证了TID唯一。
二、线程的控制
一个进程内所有线程之间的关系是平等的,任何线程都可以对同一进程的其他线程进行如下管理:
 
操作类型
系统调用
说明
创建线程
pthread_create
创建新线程时,调用线程需要给定新线程要执行的函数和对应的参数。该函数的返回值可以通过连接新线程得到。新线程创建成功,调用线程会得到新线程的ID。
终止线程
pthread_cancel
请求终止某个线程。它向目标线程发送一个终止执行的请求后立刻返回,目标线程收到请求后,在适当的时机响应终止请求。
连接以终止的线程
pthread_join
等待目标线程终止,并获取目标线程执行函数的返回值。如果一个线程可被连接,那么在终止的时候就必须连接,否则就变成僵尸线程,造成资源浪费。
分离线程
pthread_detach
将目标线程变得不可连接,默认情况线程是可被连接的。分类操作不可逆。对分离的线程任可执行终止操作。
退出线程
pthread_exit
exit
目标线程终止,其他线程正常运行。
进程以及所有相关线程全部终止。
三、线程的状态
线程的状态转移如图所示:
线程进入阻塞态一般包括以下几个原因:等待IO操作完成,等待未收到的信号量、等待获得互斥量、等待某个条件变量等等。
四、线程的调度
使用优先级队列来进行线程的调度。优先级队列是若干链表组成的数组,每个链表表示相同优先级的线程。
每个CPU包含两个优先级队列:一个是存放等待运行的线程,另一个是过期的优先级队列。
系统总是从激活的优先级队列中选择下一个要运行的线程,如果某个线程A运行了相当长的时间,且激活的优先级队列中有相同优先级的线程B在等待,则将线程A放入过期的优先级队列,CPU运行线程B。
如果激活的优先级队列中没有等待运行的线程时,则将两个优先级队列身份互换,激活的转为过期的,过期的转为激活的。
只有处在运行态和就绪态的线程才能把被调度,处于睡眠状态的线程无法被调度,将会被移除出优先级队列。
对于多CPU的计算机而言,一般情况下,一个线程总是在一个特定CPU上调度运行。但是当某些CPU过于忙碌,而某些CPU有很空闲,调度器就会把一些线程从忙碌的CPU上调度到空闲的CPU上。
五、线程模型
内核调度实体(Kernel Scheduling Entity,KSE)是可以被内核调度器调度的对象。
用户级线程、内核级线程、两级线程。
 
 
用户级线程
内核级线程
两级线程
实现原理
用户级线程库自主管理和协调线程,内核不可见。
内核负责线程的创建和管理
线程库通过内核创建若干内核级线程,利用内核级线程对用户级线程进行调度。
管理对象
用户级的线程库
操作系统内核
用户级的线程库和内核共同管理
是否需要切换特权级别
与KSE关系
多对一(M:1)
一对一(1:1)
多对多(M:N)
优点
不需要内核参与,速度快,移植性高。
实现真正的并发运行,一个线程被阻塞,不会影响到其他线程。
真正的并发运行。
内核资源消耗少。
线程管理效率高。
缺点
无法正真的并发运行,一个线程被阻塞,整个进程也会被阻塞。
对于内核调度器而言,任然是以进程为单位进行调度。
内核资源消耗大。
调度速度慢,需要切换到内核态。
一个进程的线程数量有限制。
实现复杂,需要线程库和内核共同协作。
线程安全性和可重入性
线程安全性:一个代码块(函数)可以被多个线程并发执行,而且总能够产生预期的结果,那么该代码块具有线程安全性。
可重入性:如果进程中所以线程都可以并发的对一个函数调用,并且无论执行的情况如何,该函数都可以产生预期的结果,那么这个函数是可重入的。
六、进程和线程区别
Ⅰ 拥有资源
  • 进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
Ⅱ 调度
  • 线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
Ⅲ 系统开销
  • 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
Ⅳ 通信方面
  • 线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。
 
 
 
posted @ 2020-05-20 16:53  skyliulu  阅读(260)  评论(0编辑  收藏  举报