考研408《操作系统》复习笔记,第七章《线程》

参考资料

s​​​​​​​c​​​​​​​2.1_6_线程的实现方式和多线程模型_哔哩哔哩_bilibili

多线程编程:一次性搞懂线程同步机制_哔哩哔哩_bilibili

【操作系统】进程和线程的区别_哔哩哔哩_bilibili

一、线程是啥

在前后端开发里我们就经常遇到线程,现在操作系统也遇到了,但是线程到底是什么?这里就先解释一下

1、理论理念

所谓线程,简单理解就是一个进程里【执行代码语句的顺序】

专业的说法是:线程是进程里最基本的执行单位 ,是CPU调度的最小单位

通俗可以理解成一条道路,执行一条代码就是通过一辆汽车,单线程就是只有一条路,多线程就是有多条路;

那么如果只有一条路,是不是只能一辆车跟着一辆车按顺序通过?这就是单线程

那么如果单线程里前面有一辆车故障堵住了,后面的车不就得干等?如果是多条路,那么有些车就可以到别的路上,不用在原来一条路等前面的车,这就是多线程

2、代码理解

我将用Python和JAVA两种语言的示例代码进行解释:

【Python】的多线程

先看单进程情况,单进程下,主函数依次一条一条代码从上往下按顺序执行

用【threading.Thread( )】函数之后可以创建一个多线程,并指定这个线程执行什么事情,通过 "线程.start()" 函数让其启动

那么这里创建了第二个线程 "t1",并指定执行worker这个函数,于是可以看到主函数没有去等worker函数的逻辑执行完直接就执行到底了,然后t1线程还在执行worker剩下的内容任务

这是因为相当于开辟了两条 "道路",主函数单独走自己的路,t1进程也单独走自己的路,互不影响,因此主函数直接走到底了,然后t1也同时走自己的路一路到底,不存在什么先后顺序了

下面这个例子直接创建"t1"、 "t2"两个线程,现在主函数、t1、t2相当于3条路,各自都同时往后执行,互不影响,所以能看到有时t1先输出结果、有时t2先输出结果,但是没有具体谁先谁后,因为他两同时进行的

【JAVA】示例多线程

单线程情况下,从上到下按顺序执行每一行代码

那么用【new Thread()】可以创建一个线程对象,在这个对象里可以写你要执行的内容,然后再用 "线程.start()" 的方法就可以启动这个线程

那么可以看到多线程的情况,每一次执行,输出的结果都不一样,是因为这三个进程是同时进行的,并没有明确的先后顺序之分

3、实际应用理解

但是计数看了这么多例子,可能还是有人不理解究竟为什么说线程是:进程里最基本的执行单位 ,是CPU调度的最小单位

首先,传统的计算机里,系统里的每一个程序都只能串行运行,在运行QQ时想运行音乐软件,就得停掉QQ再运行音乐程序;但是有了【进程】之后,就可以边听歌边用QQ了

但是对于一个进程里,比如QQ这个例子,我们平时可以用QQ同时看视频、文字聊天、传送文件......,那么这些事明显不是在这个进程里按顺序执行的

传统的进程内,就是CPU分时地对各个进程进行按顺序的串行执行每一行代码

因此为了处理 "高并发运行 ",现在的进程里都引入了【线程】,CPU不再是只执行进程,而是通过特定的算法分别执行各个线程

可以把【线程】理解为 "轻量级的进程",他才是CPU最基本的执行单元CPU调度的最小单位程序执行流的最小单位进程里最基本的执行单位

引入了线程之后,不仅进程之间可以并发执行,线程之间也可以并发运行

注意,引入【线程】之后,进程不再是CPU调度执行的最小单位!

而只是除了CPU之外的系统资源的分配最小单元(也就是打印机、音频播放器、摄像头......等等I/O设备的资源,是给进程的,而不是给线程的)

二、进程、线程、并发、并行这些关系

那么本人在学到这一章隐约就想起了两个知识点:

  • 1、我在第一章讲过的【并发】和【并行】
  • 2、我上一章讲的【进程】

知识点回顾:

1、【并发】和【并行】概念

2、还没引入线程的传统【进程】运行机制

那么引入了【线程】概念之后,就方便理解为什么单核CPU各个程序的并发运行,多核CPU是并行运行了

首先我们把进程比作各个正在生产产品的工厂,然后线程是里面工作的机器人,CPU是一个超大型发电机,【单核CPU就是只有一条充电线的发电机、 多核就是有多条充电线的发电机】

传统的进程模式下,CPU执行调度的单位是进程,所以只能串行的分时的执行一个一个进程,但是引入了线程之后,【线程】才是CPU调度的单位了,所以即使单核CPU也能够分时并发地执行各个进程里的线程(只不过每次同一时刻还是只能执行一条线程,所以是并发

但是如果是多核CPU,那么他就有能力同时执行多个进程里的多个线程了,那想一下多个 "机器人" 同时充电工作,不就实现了并行了吗

三、线程的实现方式

1、线程库

前面第一大点我提过,python、java都有他们各自在代码里创建线程的方式,那么调用这些方法或者对象的根源,是python、java等编程语言开发者自己写好了一套【线程库】

例如Python

2、两种实现方式

1)用户级线程(ULT, user level thread)

就是 "从用户视角能看到的线程",操作系统看不到线程

这就是基于传统进程实现的,操作系统只调度进程,所以所谓的 "线程" 只是程序员自己调用自己写的 "线程库API" 来实现,不需要操作系统来介入,所以也自然不需要CPU切换用户态、内核态

这样虽然可以避免CPU频繁变换状态,但是并不是真正意义的多线程,因为假设现在有多核CPU,但是由于操作系统只看得到进程,所以CPU还是只能分别运行一个进程而已,而不是真的同时执行多个进程的各个线程。

而且假设一个进程的某一个线程堵塞了,整个进程就堵塞了,影响别的线程正常工作.....

2)内核级线程(KLT, kernel level thread)

就是操作系统来调度操作线程

这就是引入了线程的进程,CPU之间调度运行线程,那就需要操作系统来介入管理,那也自然要由CPU从用户态切换到内核态

然后操作系统会为每个内核级线程创建各自的数据结构------------ "线程控制块"(TCB),操作系统通过对TCB管理来管理线程

虽然要CPU频繁变态,但是不会因为一个线程阻塞而影响别的线程工作;

而且是真正意义上的并发运行多线程,多线程也真正可以在多核CPU上并行运行

3)当然还有组合他两的方式

。。。。。。没啥说的,知道有就行

3、多线程模型

那么对于支持上面第2种的内核级线程的系统,根据【用户级线程】和【内核级线程】的映射关系,又可以分成这么几种模型

1)一对一

2)多对一

3)多对多

四、线程的状态与转换

和进程一样,线程也有自己的几种状态,那么这里的知识点因为大量跟进程重复,所以用进程的思维去理解即可

线程就关注【就绪】【运行】【阻塞】这三个状态,那其实什么时候用什么状态跟进程是一个道理的,所以就不多解释了,只不过我们这里不关心【创建态】和【终止态】

然后关于操作系统如何控制管理线程,也跟进程的原理一样:

进程的一些信息、id标识、状态都被记录在一个数据结构------PCB中,操作系统创建这么一个数据结构来方便管理每一个进程

而线程也一样,现在引入了线程,那么操作系统工作的重心就换成线程了,因此每个线程创建都会对应创建一个数据结构------【TCB】用来存储这个线程的信息

相关推荐
Archippus1 小时前
分块莫队学习笔记
笔记·题解·oi
n北斗1 小时前
内聚耦合软件工程
笔记
安冬的码畜日常2 小时前
【Vim Masterclass 笔记16】S07L32 + L33:同步练习09 —— 掌握 Vim 宏操作的六个典型案例(含点评课内容)
笔记·vim·自学笔记·vim宏·同步练习
隼玉2 小时前
【STM32-学习笔记-7-】USART串口通信
笔记·stm32·学习
挥剑决浮云 -2 小时前
QT信号槽 笔记
开发语言·笔记·qt
明月清了个风2 小时前
数据结构与算法学习笔记----中国剩余定理
笔记·学习
iamyzs2 小时前
【张雪峰高考志愿填报】合集
考研·高考·高考志愿填报指导·张雪峰
安冬的码畜日常3 小时前
【Vim Masterclass 笔记17】第八章 + S08L34:Vim 的可视化模式(一)
笔记·vim·vim可视化模式·visual mode
Mae_cpski3 小时前
【React学习笔记】第三章:React应用
笔记·学习·react.js