避免死锁的办法是否有效与采用的算法由很大的关系。有效避免死锁的算法必须能预见将来可能发生的事情,以便在死锁发生前就能察觉出它们的存在。这种遇见类型的代表算法是Dijkstra E W于1968年提出的银行家算法,是因为该算法可用于银行系统。
算法概述:
(1)设计思想:当新进程进入系统时,它必须说明对各类资源类型的实例的最大需求量。这一数量不能超过系统各类资源的总数。当进程申请一组资源时,该算法需要检查申请者对各类资源的最大需求量,如果系统现存的各类资源的数量可以满足当前它对各类资源的最大需求量时,就满足当前的申请;否则,进程就必须等待,直到其他进程释放足够的资源为止。换言之,仅当申请者可以在一定时间内无条件的归还它所申请的全部资源时,才能把资源分配给它。
(2)从设计思想中,我们可以知道,我们的几个主要变量(矩阵中:进程用 "i" 表示, 资源用 "j" 表示)
- 新进程的最大需求量(max):这个输入是一个矩阵,当进程进入系统,每个进程的资源所需量都要判断,如果系统最大的资源申请都不能满足,那肯定是不可以的,比如:进程 "i" , 需要 “j” 资源 为 8,而系统中,j 资源在没有分配的情况下,最大是 5,那该进程肯定执行不了。
- 可利用资源向量(Available):这是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个
- 分配矩阵(Allocation):这是一个矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K
(3)窗体设计大致如下
一、实验目的
1、理解死锁产生的基本原理,以及死锁的必要条件;
2、掌握死锁避免的基本原理与思路。
二、实验内容
试利用银行家算法对死锁避免算法进行模拟,确保系统在冬天申请资源的同时,永远不会陷入不安全状态。
具体要求如下:
(1)程序中进程数量、资源种类数在程序运行时由用户输入;
(2)程序中的资源状态表结构根据输入的进程数量、资源种类数由程序动态生成;
(3)资源状态表中的数量既可以通过随机函数自动产生,也可以由用户手工输入;
(4)程序首先判断系统是否安全,然后在系统安全的前提下,由用户手动完成资源申请,
其方法是:先输入或选择进程,然后输入该进程的资源申请要求;
(5)针对用户输入的资源申请,系统应视情况不同给出如下四种执行结果:
1.显示“资源申请不合理”;
2.显示“资源申请超过最大可用资源数,资源不够分配”;
3.显示“找不到安全序列,进程资源申请不予满足”;
4.先显示所找到的安全序列,进而告知用户资源已被分配,并同步修改资源状态表中相关数据。
三、实验要求
1、写出程序,并调试程序,要给出测试数据和实验结果。
2、整理上机步骤,总结经验和体会。
3、完成实验报告和上交程序。
四、窗体设计和源码
(1)窗体
(输入数据的时候,同一行不同数据用逗号,不同行用空格)
(2)源码
using System;
using System.Windows.Forms;
namespace banker
{
public partial class Form1 : Form
{
public int n ; //定义进程数目,赋值于n
public int m ; //定义资源分类数,赋值于m
int[,] Allocation; //定义
int[,] Max; //定于进程所需的最大资源数
int[] Available; //定于系统资源数字
int[,] Need; //定于进程还需要的资源
int[] Require; //定于进程申请的资源数
string order;//输出安全序列
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void input_Click(object sender, EventArgs e)
{
n = Convert.ToInt32(tb_proNum.Text); //输入进程数目
m = Convert.ToInt32(tb_resouseClass.Text); //输入资源分类
}
private void button2_Click(object sender, EventArgs e)
{
if (rb_allocation.Checked)
{
tb_output.Text += "\r\nAllocation矩阵\r\n";
string[] str = tb_datainput.Text.Split(' ');
Allocation = new int[n, m];
for (int i = 0; i < n; i++)
{
tb_output.Text += "\r\n";
string[] temp = str[i].Split(',');
for (int j = 0; j < m; j++)
{
Allocation[i, j] = Convert.ToInt32(temp[j]);
tb_output.Text += " " + Allocation[i, j];
}
}
}
else if (rb_available.Checked)
{
tb_output.Text += "\r\nAvailable向量\r\n";
string[] str = tb_datainput.Text.Split(',');
Available = new int[m];
for (int i = 0; i < m; i++)
{
Available[i] = Convert.ToInt32(str[i]);
tb_output.Text += " " + Available[i];
}
}
else//输入max矩阵
{
tb_output.Text += "\r\nMax矩阵\r\n";
string[] str = tb_datainput.Text.Split(' ');
Max = new int[n, m];
for (int i = 0; i < n; i++)
{
tb_output.Text += "\r\n";
string[] temp = str[i].Split(',');
for (int j = 0; j < m; j++)
{
Max[i, j] = Convert.ToInt32(temp[j]);
tb_output.Text += " " + Max[i, j];
}
}
}
}
private void button3_Click(object sender, EventArgs e)
{
int PID = 0;
bool[] finish = new bool[n];
for (int i = 0; i < n; i++)
{
finish[i] = false;
}
if (tb_pid.Text == "")
;
else
PID = Convert.ToInt32(tb_pid.Text);
int bigger_1 = 0;
int bigger_2 = 0;
///计算Need矩阵///
Need = new int[n, m];
tb_output.Text += "\r\nNeed矩阵\r\n";
for (int i = 0; i < n; i++)
{
tb_output.Text += "\r\n";
for (int j = 0; j < m; j++)
{
Need[i, j] = Max[i, j] - Allocation[i, j];
tb_output.Text += " " + Need[i, j];
}
}
///输入Require///
if (tb_require.Text == "")
{
Require = new int[m];
for (int i = 0; i < m; i++)
{ Require[i] = 0; }
PID = 0;
tb_output.Text += "\r\n检测当前状态是否安全中…\r\n";
if (CheckSecure(Available, finish, Need, Allocation))
{
tb_output.Text += "系统目前安全" + "安全序列" + order;
}
else
{
tb_output.Text += "找不到安全序列,进程资源申请不予满足";
}
}
else
{
string[] str = tb_require.Text.Split(',');
Require = new int[m];
for (int i = 0; i < m; i++)
{
Require[i] = Convert.ToInt32(str[i]);
if (Require[i] > Need[PID, i])
bigger_1++;
if (Require[i] > Available[i])
bigger_2++;
}
///检查///
if (bigger_1 != 0)
{
tb_output.Text += "\r\n错误:进程申请的资源多于说明的最大量,系统无法满足\r\n";
}
else if (bigger_2 != 0)
{
tb_output.Text += "\r\n进程" + tb_pid.Text + "暂时阻塞\r\n";
}
else
{
int[] temp_available = Available;
int[,] temp_allocation = Allocation;
int[,] temp_need = Need;
for (int j = 0; j < m; j++)
{
temp_available[j] -= Require[j];
temp_allocation[PID, j] += Require[j];
temp_need[PID, j] -= Require[j];
}
if (CheckSecure(temp_available, finish, temp_need, temp_allocation))
{
Available = temp_available;
Allocation = temp_allocation;
Need = temp_need;
tb_output.Text += "\r\n系统处于安全状态,且已经分配完毕\r\n" + "安全序列" + order;
}
else
{ tb_output.Text += "\r\n该请求将导致系统处于不安全状态,已经撤销分配\r\n"; }
}
}
}
///检查安全状态///
public bool CheckSecure(int[] work, bool[] finish, int[,] temp_need, int[,] temp_allocation)
{
int num = 0;//need[i]<=work[i]的个数
order = "";
int[] wor = work;
bool[] finis = finish;
int[,] temp_nee = temp_need;
int[,] temp_allocatio = temp_allocation;
int K = 0;
while (K < 10)
{
for (int i = 0; i < n; i++)
{
if (!finis[i])
{
for (int j = 0; j < m; j++)
{
if (temp_nee[i, j] <= wor[j])
num++;
}
if (num == m)
{
for (int j = 0; j < m; j++)
{
wor[j] += temp_allocatio[i, j];
}
finis[i] = true;
order += i;
num = 0;
}
else num = 0;
}
else
if (checkFinish(finis))
return true;
}
K++;
}
if (checkFinish(finis))
return true;
else
return false;
}
public bool checkFinish(bool[] f)
{
int num = 0;
foreach (bool k in f)
{
if (k)
num++;
}
if (num == f.Length)
return true;
else return false;
}
private void tb_output_TextChanged(object sender, EventArgs e)
{
}
}
}
(3)运行效果
五、总结
这个程序设计的比较保守,因为输入的数据都是提前计算好的,然后基本上运算的效果和预想是一致的,但是并没有设计出,在require资源申请的时候,是随机产生所需要的资源,只能用户手动输入。然后输入输出我用的都是textbox这个控件,也可以换成表格。有改进空间。