说到进程的由来,就不得不提早期的未配置OS的计算机系统以及后来的单道批处理系统,在这种系统中的程序是顺序执行的,比如说在没有配置操作系统的计算机系统采用的人工操作方式,,程序员将事先已经穿孔的纸带,装入纸带输入机,输入机将这些程序与数据输入,然后启动计算机运行,这时就会有一个问题,就是cpu的速度与I/O设备的速度时严重不匹配的,同时还有一个更严重的问题,在进行输入输出操作的时候,cpu与其他计算机资源都是空闲的,所以说计算机的资源利用率很低。
![](https://img-blog.csdnimg.cn/20190726201356610.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0dWRlbnRzX18=,size_16,color_FFFFFF,t_70)
人们为了提高系统资源的利用率跟吞吐量,后来出现了脱机输入输出方式(外围机代替人工),再后来的单道批处理系统。单道批处理系统是什么意思呢,就是先把一批作业以脱机的方式输入到磁带上,在系统中的监督程序的控制下,使得这批作业能够一个接着一个连续的处理,系统对作业的处理是成批的,但内存中只有一个作业,
虽然说这种方式可以减少机器的等待空闲时间,但是问题依旧,就是I/O处理的时候,cpu还是在等待,如下图所示
![](https://img-blog.csdnimg.cn/20190726195337205.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0dWRlbnRzX18=,size_16,color_FFFFFF,t_70)
为了进一步提高资源的利用率以及系统的吞吐量,后来就有了多道批处理系统,在这个系统当中,用户提交的作业先放入到外存当中,形成一个队列,即“后备队列”,然后由作业调度程序按照一定的算法,从后备队列中选择若干个作业调入到内存,注意,这里是若干个,他们可以共享cpu以及系统中的资源,因为内存中有若干个程序,假设程序A在运行,当其因需要进行I/O操作而暂停执行的时候(此时cpu空闲),可以再次调度程序B,让cpu在A程序进行I/O操作时同时运行B,cpu就可以很好的达到一个忙碌的状态,如下图
![](https://img-blog.csdnimg.cn/20190726201530129.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0dWRlbnRzX18=,size_16,color_FFFFFF,t_70)
关于多道批处理系统的优缺点就不多说了,关键在这里,我们需要理解并发的概念,在多道程序环境下,并发性是指一段时间内宏观上有多个程序在同时执行,但微观上,程序是分时交替的运行的,比如像上一张图片的情况就是程序并发执行,与之概念相似的是并行,并行就是真正意义上的同一个时刻执行了,如果说一个计算机有多个处理机时,就可以实现程序的并行执行。
这样看来,只要能够使程序并发执行,我们的问题(资源的利用率以及系统资源吞吐量)就可以得到解决了,但其实不然
举个例子,程序A,B在共享一个变量N,程序A对N进行加一操作,即N=N+1,程序B负责两件事,打印N,将N置0(print(N),N=0)
由于程序并发执行的特点,两个程序以不同的速度运行,这样就会出现几种情况(假设此时N=n)
1.如果程序A,在程序B之前执行,那么此时打印值为 n+1
2.如果程序A在程序B的print(N)与N=0中间执行的话,打印值为 n
3.如果程序A在程序B之后执行的话,打印值为 0
发现了没,每次执行的结果都是不一样的用专业术语来说,就是失去了可再现性,我用两个线程模拟进程的执行实现上面的过程
(具体代码跟测试结果我放在文章最后,接下来重点说下进程)
进程的由来
前面有说到程序并发执行会导致运行结果不可再现,这一点就可以以说明程序的运行失去了意义,所以为了能够使程序并发执行,并且能够对并发的程序加以控制跟描述,人们引入了进程这个概念,这个概念的引出是为了能够让参与并发执行的每个程序能够独立的运行(注意,是独立),操作系统为了达到这个目的,设置了PCB(进程控制块),操作系统利用PCB"监控"进程的活动情况,进而去控制与管理进程,由程序段,数据,PCB三部分组成了进程实体。
书本定义:“进程是进程实体的运行过程,是系统进行资源分配和调度的独立单位”,当然后来的线程的概念引出,系统实际调度的是线程,而资源分配的独立单位是进程。
接下来说一下,进程与程序的区别:
1.进程是动态的,通过上面也可以知道,进程是为并发而生的,某个程序需要被执行的时候,系统需要为它创建进程(申请PCB,分配资源...),然后由调度而执行,由撤销而消亡(归还PCB,资源...),所以进程是由生命周期的,而程序是静态的,说白了,就是存放在某种介质上(比如说磁盘)上的代码集合。
2.并发性,前面也说到了,程序是不能参与并发的,后果比较严重,参与并发的是进程
3.独立性,指的是一个进程实体,可以独立运行,独立接受资源,接受调度。实现这一点的是PCB
4.异步性,进程的运行是走走停停的速度不可预知,这一点导致了程序并发执行结果的不可再现,那进程又是如何解决这些问题的呢?靠的是进程同步机制,比如说比较经典的生产者消费者问题。
以上这些知识点我是参照《计算机操作系统》这本教材来写的,加入了一些自己的理解,推荐大家去读下这本教材,很棒!
最后,是上面那个模拟进程A,B运行的代码
//Resource类描述资源以及对资源的操作
- class Resource{
- private int n;
- Resource(int n){
- this.n=n;
- }
- public void add()
- {
- n=n+1;
- }
- public void print() {
- System.out.println(n);;
- n=0;
- }
- }
- //AddProcess 线程模拟进程A
- class AddProcess implements Runnable{
- private Resource r;
- AddProcess(Resource r){
- this.r=r;
- }
- @Override
- public void run() {
- //for(int i=0;i<10;i++)
- while(true)
- r.add();
- }
- }
- //PrintProcess 线程模拟进程B
- class PrintProcess implements Runnable{
- private Resource r;
- PrintProcess(Resource r){
- this.r=r;
- }
- @Override
- public void run() {
- //for(int i=0;i<10;i++)
- while(true)
- r.print();
- }
- }
- public class ProcessTest {
- public static void main(String[] args) {
- Resource r=new Resource(10);
- AddProcess ap=new AddProcess(r);
- PrintProcess pp=new PrintProcess(r);
- Thread t1=new Thread(ap);
- Thread t2=new Thread(pp);
- t1.start();
- t2.start();
- }
- }
- 测试结果如下
- 有兴趣可以分析下为何会出现这些结果哟