概念
在多道程序环境下,进程数目往往多于处理机数目,致使它们竞争使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之执行。一个作业从提交开始,往往要经历三级调度:高级调度、中级调度、低级调度。
- 高级调度:调度对象是作业。
- 中级调度:提高内存利用率和系统吞吐量。
- 低级调度:它所调度的对象是进程。进程调度是最基本的一种调度。进程调度方式有两种调度方式:非抢占方式和抢占方式(基于优先权,短作业优先,时间片原则)。
作业调度和进程调度的区别
作业调度为进程活动做准备,进程调度使进程活动起来
作业调度次数少,进程调度次数多
有的系统不设作业调度,但进程调度必不可少
进程调度算法
FCFS先来先服务
该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)。
短作业优先
短作业优先调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
高优先权优先调度算法(动态优先权)
动态优先级调度算法是指在创建进程之初,先赋予其一个优先级,然后其值随着进程的推进或等待时间的增加而改变,以便获得更好的调度性能。例如,可以规定在就绪队列中的进程随其等待的时间的正常,使其优先级相应提高。若所有的进程都具有相同的优先级初值,则最先进入就绪队列的进程会因为其优先级变得最高,而优先获得处理机,这相当于FCFS算法。若所有的就绪进程具有各不相同的优先级初值,那么对于优先级初值低的进程,在等待了足够的时间后,也可以获得处理机。
基于时间片的轮转调度算法
在分时系统中,为保证能及时响应用户的请求,必须采用基于时间片的轮转式进程调度算法。每次调度时,把CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几ms
到几百ms
。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。
死锁
产生死锁原因
竞争资源(多个进程竞争共享的资源),进程间推进顺序非法(进程请求和释放的资源顺序不当)
产生死锁的条件
互斥条件,请求和保持条件,不剥夺条件,环路等待条件。
处理死锁的几种条件
预防死锁,避免死锁,检测死锁,解除死锁。
银行家算法
它是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。
安全序列是指一个进程序列{P1,…,Pn}
是安全的,即对于每一个进程Pi(1≤i≤n)
,它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )
当前占有资源量之和。(即在分配过程中,不会出现某一进程后续需要的资源量比其他所有进程及当前剩余资源量总和还大的情况)
注:存在安全序列则系统是安全的,如果不存在则系统不安全,但不安全状态不一定引起死锁。
原理过程:系统给当前进程分配资源时,先检查是否安全:在满足当前的进程X资源申请后,是否还能有足够的资源去满足下一个距最大资源需求最近的进程(如某进程最大需要5个单位资源,已拥有1个,还尚需4个),若可以满足,则继续检查下一个距最大资源需求最近的进程,若均能满足所有进程,则表示为安全,可以允许给当前进程X分配其所需的资源申请,否则让该进程X进入等待。
(注:检查过程中,每拟满足一个进程,则进行下个检查时,当前可用资源为回收上一个进程资源的总值,每满足一个进程表示此进程已结束,资源可回收。)
代码实现:
1 |
|
Java死锁的实例
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
在 Java 里面不恰当的使用锁且出现同时要锁多个对象时,会出现死锁情况:
1 | import java.util.Date; |
以上代码运行输出结果为:
1 | Tue May 05 10:51:06 CST 2015 LockB 开始执行 |
此时死锁产生。
为了解决这个问题,我们不使用显示的去锁,我们用信号量去控制。
信号量可以控制资源能被多少线程访问,这里我们指定只能被一个线程访问,就做到了类似锁住。而信号量可以指定去获取的超时时间,我们可以根据这个超时时间,去做一个额外处理。
对于无法成功获取的情况,一般就是重复尝试,或指定尝试的次数,也可以马上退出。
1 | import java.util.Date; |