序言:
我们知道多线程是现代操作系统中一个很重要的组成部分。它经常在面试过程中或者在实际运用过程中都会碰到的一个比较难的一个问题,所以这篇文章所属的一个系列,将浅显的记录下博主的多线程学习的一个过程。
首先呢,说起线程的起源,我们不得不提就是进程的概念。然而一开始也并不是直接就有的进程的,而是由多道处理程序环境下,演化而来的。
由于多道程序有间断性和失去封闭性、以及不可再现性,催生出了进程的产生。浅显的来说,进程就可以能使程序并发的执行程序,并加以描述和控制。这又是为什么呢?因为其中有一个专门的数据结构称为进程控制块。那么什么是进程?又是进程控制块呢?什么又是线程呢?如何处理多线程呢?我们接着看下去。
一. 为什么要引入进程
这个部分可以分两个部分来看:
1.在20世纪60年代中期,IBM开发了OS/360操作系统是第一个多道程序的批处理系统,在引入程序间的并发执行功能后,虽然提高了系统的吞吐量和资源的利用率,但同时也带来了一系列的问题:(1)间断性。程序在并发执行时,由于它们共享系统资源,它们之间必将会形成互相制约的关系。(2)失去封闭性。当系统中存在着多个以可以并发执行的程序时,系统中的各种资源将为他们所使用。这就意味着其中一个程序在运行时。其环境都必然会受到其他程序的影响。这不同于我们现在对操作系统已有的观念,其实这有点儿像多线程中对共享变量不加锁的情况。(3)不可再现性。一段程序的执行出现了多种可能,而且出现了不确定性。我们知道程序的确定性是一个基本的要素。
2.我们进一步来看待这一个问题。在第一点中我们提到了资源利用率和系统吞吐量的问题,并且间断性的原因在于它们之间互相制约。这又是为什么呢?这是因为我们计算机的存储层次结构之间访问速率不匹配的原因造成的。CPU的速度比内存快,内存比硬盘快,硬盘又比读取网络资源快。为解决这个问题,操作系统就由此诞生了。一旦开机后,操作系统进入内存,它就是老大了。对我们计算机一个全局的掌控。它自带各种算法,其目的是寻找到一个中庸之道,让我们的计算机得以平衡和稳定地运行。进程就是在操作系统演化过程中产生的。进程也服从操作系统一系列规则运行。
二.进程的定义
首先,进程可以简单的定义为一个正在执行中的程序。举个例子:JVM是一个进程,QQ是一个进程,浏览器是一个进程等等。我们可以打开任务管理器可以看到,我们的电脑运行着很多很多的进程。
同时我们又可以看到CPU的利用率是忽高忽低的,这是为什么呢?
肯定不是因为抽风,而是因为在操作系统的管理下,由进程调度算法,不断地有进程在内存中换进换出,进程的执行是要占有CPU的,一个CPU同一时刻只能运行一个进程中的某一指令,进程有时候占用CPU多,有时候占用CPU少。不同的进程,所需要的CPU等资源也就是不一样的。所以就出现了这样一个现象。不光如此,进程执行的同时,也要消耗计算机的各种资源:CPU、内存、网络、IO、文件系统。
所以这说明了两点:进程是拥有资源的独立单位。进程同时又是一个可独立和分派的基本单位。
然后,我们再具体说明进程的概念:一个具有独立功能的程序在一个数据集合上的一次动态执行的过程。
这里要注意进程和程序的区别。一个是动态的,一个是静态的。一个静态的程序静静的躺在硬盘上(java编译后的.class文件便是如此),通过操作系统分给它一个进程控制块,在内存中让CPU执行起来,这个执行过程,称为进程。它是一个动态的过程。
三. 进程的组成
程序的代码
程序处理的数据
要知道现在执行哪条指令,程序计数器PC中的值指示将运行的指令。
CPU寄存器会动态变化,一组通用寄存器的当前值,堆,栈等;
各种系统资源,内存,外存,网络。
包含了正在运行的一个程序的所有状态信息,这些信息基本都记录在进程控制块PCB(Process Control Block)中:
四. 进程的特点
(a)并发性:
并发:在一段时间内有多个进程在执行。如果这个时间很小,给人一种感觉是多个进程在一起执行一样
并行:在一个时刻有多个进程在执行。一个CPU在同一时刻没有办法执行多个程序,只能执行一个程序,没有办法并行。
并发和并行时间的粒度是不一样的。
(b)动态性:很好理解,进程的实质是程序的执行过程。进程有一定的生命周期:它由创建而产生,由调度而执行,由撤销而消亡。
(c)独立性:从两个方面来看,正确性,其他进程不会破坏到我们进程不会破会我们代码,不会破坏我们的数据 ——内存管理中页表的功能——使不同的程序访问不同的地址空间, 不可能越过地址空间,越过会产生缺页异常,页错误。
(d)制约性:与其他程序的交互和制约,同步互斥
五 进程控制块(重要)————进程的唯一标志。和我们的身份证号一样重要,里面有一个进程标识PID,同样在任务管理器中也可以看到:
进程和进程控制块是一对一的关系,进程创建,进程控制块创建,进程消失,进程控制块消失。
进程控制块PCB有三大类信息:
(一)进程标识信息一个PCB唯一标识了一个进程,进程ID识别出来到底代表着哪一个程序在执行,或者说一个程序执行了几次,都可以通过进程控制块的进程标识来体现。还有标识这个进程是属于哪一个用户的,这个进程的父进程(创建这个进程的进程)。
(二)处理机状态信息——主要是寄存器。
CPU在执行过程中会使用CPU做很多的事情,比如说,加减乘除计算保存、保存的状态信息(是否溢出)、执行过程(执行到什么地方了,栈在什么地方,堆在什么地方)、程序计数器寄存器 、栈指针寄存器。
用户可见寄存器,程序使用的数据,地址
控制和状态寄存器,程序计数器pc,程序状态字PSW
栈指针,过程调用/系统调用/中断处理和返回时需要用到
(三)进程控制信息
操作系统对进程的管理和控制:让它处于运行的状态还是等待、就绪。进程临时的执行的特征。
进程间的通信
内存信息:代码
进程控制块的连接信息:PCB控制块,父子进程之间的关系,管理信息
六 进程的状态(重要)
进程创建:创建并不是立即运行的,而是进入一个就绪状态,等待调度算法占据CPU运行
进程运行:内核选择一个就绪的进程,让它占用处理机(cpu)并执行
进程等待(阻塞):三种情况:(1)请求并等待系统服务,无法马上完成;
(2)某种操作(和其他进程协调工作),无法马上完成;(3)需要的数据没有到达
进程自己触发阻塞,因为只有自己才知道何时需要等待某事件 。进程只能自己阻塞自己。
进程唤醒:需要的资源可被满足,等待的事件到达,都意味着可将该进程的PCB插入到就绪队列 。注意,被唤醒后不能立即执行,需要进入到就绪状态,等待占有CPU。因为自身没有占用cpu执行,所以只能被OS或其他进程唤醒
进程结束:结束情况:自愿(正常退出,错误退出),强制性的(致命错误,被其他进程所杀)
综上我们称之为五状态图:
其中多了一条运行到就绪状态,因为该进程时间片用完了,就绪对列有很多需要处理,所以CPU只分配一点点时间给每一个进程。操作系统让它退出了CPU,等待再次被调度。同时操作系统根据线程优先级加之调度算法调度其他线程。首先是操作系统调度器完成调度。操作系统时钟在起作用:知道执行了多久,一旦超时,操作系统就会得到感知,运行态的进程就会停下来,变成就绪态,再选择一个就绪太的进程占用CPU来执行。
PS:关于调度算法又是一门学问了,我们之后再讲,先占坑。
接着我们有七状态图:引入进程挂起,和进程激活。
进程挂起和进程阻塞是不太一样的。以及为什么要进程挂起?
进程挂起:进程没有占有内存空间。——和内存管理有紧密的联系。在虚拟内存管理的时候,运行的程序有可能是它把它一部分空间会导到硬盘上去,腾出更多的空间给后面需要的程序使用。
现在运行的程序就是进程,进程如果没有占有内存空间,也就意味着进程被切换到了(swapout)到硬盘上去了,这时候就没有占有内存空间了,这时候就称为进程挂起。
挂起分两类:阻塞挂起和就绪挂起。
阻塞挂起:进程在磁盘上等待某个事件的出现,第一,已落在磁盘上去了,第二,它还在等待某个事件的出现
就绪挂起:进程本身处于就绪状态。这时候它的地址空间的内容 也是在硬盘上,这时候下面被换如到内存之后,它本身就处于就绪态。
一个是进程本身处于阻塞的状态被挂起,还一个是进程属于就绪的状态时被挂起。
阻塞到阻塞挂起:内存不够用了,会把阻塞的一些进程变到阻塞挂起,这时候阻塞进程所占用的内存空间就会腾出来给其他的就绪态,和正在运行的进程所使用。
就绪到就绪挂起:一般来说,就绪的进程会比阻塞的进程优先级要高一些。操作系统就会优先选择处于阻塞状态的进程变到阻塞挂起状态,把它的内存给释放出来
阻塞挂起到就绪挂起:当处于阻塞挂起的进程,事件得到满足时,这个时候,进程会变成就绪态,但是需要注意,这个进程本身就是还在挂起在硬盘上,这个时候我们只是把阻塞挂起到就绪挂起,但是进程本身的所有的资源,所有的内存的数据都还在硬盘上,我们只是把它的状态变了。
---------------------
作者:吴晶鑫
来源:CSDN
原文:https://blog.csdn.net/weixin_37864819/article/details/78451243
版权声明:本文为博主原创文章,转载请附上博文链接!