死锁
两个或者两个以上的线程在执行过程中由于竞争资源而造成的阻塞问题,若无外力作用,他们将无法推进下去,此时系统处于死锁状态。
安全序列
安全序列是指对当前申请资源的进程排出一个序列,保证按照序列分配资源完成进程,不会发生死锁问题
我们假设有进程P1,P2,…Pn
则安全序列要求满足:Pi(1<=i<=n)需要资源<=剩余资源 + 分配给Pj(1 <= j < i)资源
示例
Process | Allocation | Need | Available |
---|---|---|---|
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 0 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
采用银行家算法
Process | Work | Allocation | Need | Available |
---|---|---|---|---|
P0 | 1 6 2 2 | 0 0 3 2 | 0 0 1 2 | 1 6 5 4 |
P3 | 1 6 5 4 | 0 3 3 2 | 0 6 5 2 | 1 9 8 6 |
P4 | 1 9 8 6 | 0 0 1 4 | 0 6 5 6 | 1 9 9 10 |
P1 | 1 9 9 10 | 1 0 0 0 | 1 7 5 0 | 2 9 9 10 |
P2 | 2 9 9 10 | 1 3 5 4 | 2 3 5 6 | 3 12 14 14 |
我们来分析一下银行家算法
现有资源为 1 6 5 4,P0 线程需要0 0 1 2,足够分配给它,我们分配给线程P0,等到P0 运行完回收资源,Avaliable 为1 6 5 4。
然后线程P1,需要资源1 7 5 0,Avaliable < Need,不分配
线程P2 需要资源2 3 5 6,Avaliable < Need,不分配
线程P3 需要资源0 6 5 2,分配给它然后回收资源,Avaliable 为1 9 8 6
线程P4 需要资源0 6 5 6,分配给它然后回收资源,Avaliable 为1 9 9 10
返回继续判断P1,需要资源1 7 5 0,分配给它然后回收资源,Avaliable 为2 9 9 10
然后P2,需要资源2 3 5 6,分配给它然后回收资源,Avaliable 为3 12 12 14
用java来实现一下银行家算法
package com.os;
import java.util.Scanner;
/**
* Description:v银行家算法
*
* @author:仙女萌
* @Date 2018/12/29 16:32
*/
public class BankerAlgorithm {
private static Scanner scanner = new Scanner(System.in);
//资源数量
private int resource;
//线程数量
private int thread;
//资源总数量
private int max[];
//剩余资源数量
private int avilable[];
//最大需求矩阵
private int[][] applymax;
//已分配资源数量
private int[][] allocation;
//还需要资源是数量
private int need[][];
boolean F[];
/**
* 一维数组的输入
* @param n
* @return
*/
private int[] inputone(int n){
int[] number = new int[n];
for(int i = 0;i < resource;i++){
number[i] = scanner.nextInt();
}
return number;
}
/**
* 二维数组的输入
* @param m
* @param n
* @return
*/
private int[][] inputtwo(int m,int n){
int[][] number = new int[m][n];
for(int i = 0;i < m;i++){
System.out.print("进程p"+i+":");
for(int j = 0;j < n;j++){
number[i][j] = scanner.nextInt();
}
}
return number;
}
/**
* 数组的初始化
*/
public void init(){
System.out.print("请输入资源数量:");
resource = scanner.nextInt();
System.out.print("请输入线程数量:");
thread = scanner.nextInt();
System.out.print("请输入最大资源数量:");
max = inputone(resource);
System.out.println("请输入每个线程最大申请资源总数");
applymax = inputtwo(thread,resource);
System.out.println("请输入资源分配情况");
allocation = inputtwo(thread,resource);
//剩余资源
avilable = max.clone();
for(int i = 0;i < resource;i++){//资源个数
for(int j = 0;j < thread;j++){//线程个数
avilable[i] -= allocation[j][i];
}
}
need = new int[thread][resource];
//还需要资源need = apply-allocation
for(int i = 0;i < thread;i++){
for(int j = 0;j < resource;j++){
need[i][j] = applymax[i][j] - allocation[i][j];
}
}
F = new boolean[thread];
show();
System.out.println("安全性检查");
int[] work = avilable.clone();
safe(work,allocation,need);
}
/**
* 输出
*/
private void show(){
int[] work = avilable.clone();
//最大资源数量
System.out.print("资源总数:");
for(int i = 0; i < resource; i++){
System.out.print(max[i]+" ");
}
System.out.println();
System.out.print("可利用资源向量:");
for(int j = 0;j < resource;j++){
System.out.print(work[j]+" ");
}
System.out.println();
System.out.println("NAME"+"\t\t"+"MAX"+"\t\t"+"ALLOCATION1"+"\t\t"+"NEED");
for(int i = 0 ;i < thread;i++){//线程
System.out.print("p"+i+"\t\t\t");
for(int j = 0;j <resource;j++){
System.out.print(applymax[i][j]+" ");
}
System.out.print("\t\t");
for(int j = 0;j < resource;j++){
System.out.print(allocation[i][j]+" ");
}
System.out.print("\t\t");
for(int j = 0;j <resource;j++){
System.out.print(need[i][j]+" ");
}
System.out.println();
}
}
/**
* 安全性算法
* @return
*/
public boolean safe(int[] work,int[][] allocation,int[][] need){
boolean s = true;
int count = 0;
int count1 = -1;
for(int i = 0;i <thread;i++){
F[i] = false;
}
// System.out.println("还原finish");
System.out.println("name"+"\t\t"+"WORK"+"\t\t"+"NEED"+"\t\t"+"ALLOCATION"+"\t\t\t"+"WORK+ALLOCATION"+"\t\t"+"FINISH");
int way[] = new int[thread];
for(int i = 0;i < thread;i++) {
s = true;
//判断资源是否足够分配
for (int j = 0; j < resource; j++) {
if (work[j] < need[i][j]) {//avaliable <need
s = false;
break;
}
}
// System.out.println(i+"检查完毕 s =="+s+" "+"F[i] ==" +F[i]);
//资源足够分配,那么就分配资源
if (s == true && F[i] == false) {
F[i] = true;
way[count++] = i;
System.out.print("p"+i+"\t\t\t");
for (int j = 0; j < resource;j++) {
System.out.print(work[j]+" ");
}
System.out.print("\t\t");
for (int j = 0; j < resource; j++) {
System.out.print(need[i][j]+" ");
}
System.out.print("\t\t");
for (int j = 0; j < resource; j++) {
System.out.print(allocation[i][j]+" ");
}
System.out.print("\t\t\t\t");
for (int j = 0; j < resource; j++) {
work[j] = work[j] + allocation[i][j];
System.out.print(work[j]+" ");
}
System.out.print("\t\t\t\t");
System.out.println(F[i]);
}
/**
* 如果循环一遍没有任何的线程被分配资源,那么这个线程是不安全的
*/
if (i == thread - 1 && count == count1) {
System.out.println("该线程不安全");
return false;
}
/**
* 从头再继续循环
*/
if (count < thread && i == thread - 1) {
// System.out.println("count < thread && i == thread - 1");
count1 = count;
i = -1;
}
if (count == thread) {
System.out.print("该线程的安全序列为:");
for (int j = 0; j < thread; j++) {
System.out.print(way[j]+" ");
}
System.out.println();
return true;
}
}
return false;
}
public boolean update(int p,int[] request){
for(int i = 0;i < resource;i++){
if(request[i] > need[p][i]){
System.out.println("线程不安全");
return false;
}
if(request[i] > avilable[i]){
System.out.println("线程不安全");
return false;
}
}
return true;
}
/**
* 预分配
*/
public void preAll(){
boolean b = true;
// 预分配资源
System.out.print("请选择进程申请资源: p");
int p = scanner.nextInt();
int[] request = new int[resource];
System.out.print("申请资源数:");
request = inputone(resource);//需要请求的资源
int[] work1 = avilable.clone();
int [][] all = allocation.clone();
int n[][] = need.clone();
int[] work2 = avilable.clone();
/**
* 输入合法
*/
if(update(p,request) == true){
//预分配
for(int i = 0;i < resource;i++){
work1[i] = work1[i] - request[i];
all[p][i] = all[p][i] + request[i];
n[p][i] = n[p][i] - request[i];
if(n[p][i] != 0){//数据不为0
b = false;
}
}
if(b == true){//进程可以运行完毕
for(int i = 0;i < resource;i++){
work1[i] = all[p][i]+work1[i];
all[p][i] = 0;
}
}
}
work2 = work1.clone();
//public boolean safe(int[] work,int[][] allocation,int[][] need){
if(safe(work2,all,n)){//安全性检查
//线程安全2
avilable= work1.clone();
allocation = all;
need = n;
}
show();
}
public void menu(){
while(true){
System.out.print("是否预分配(Y/N):");
char ch = scanner.next().charAt(0);
switch (ch){
case 'Y':
preAll();//预分配
break;
case 'N':
System.out.println("退出系统");
System.exit(0);
break;
default:
System.out.print("输入不合法,重新输入:");
break;
}
}
}
public static void main(String[] args) {
BankerAlgorithm banker = new BankerAlgorithm();
banker.init();
banker.menu();
}
}
运行结果: