目录
一、分类
二、预防死锁
1、破坏互斥条件
2、破坏不剥夺条件
3、破坏请求和保持条件
4、破坏循环等待条件
5、总结
三、避免死锁
1、什么是安全序列
2、安全状态和不安全状态
3、银行家算法
(1)核心思想
(2)例子
(3)代码实现
(4)考点
四、死锁的检测和解除
1、死锁的检测
(1)资源分配图
(2)例子
2、死锁的解除
五、总结
在进程提出资源申请时,先预判此次分配是否会导致系统进入不安全状态。如果会进入不安全状态,就暂时不答应这次请求,让该进程先阻塞等待。
1、若我们有如下例子,我们计算出各个进程最大还需要多少,和剩余多少
2、我们依次对比各个进程需要的资源和剩余资源
此时P1一定可以顺利执行完毕,所以将P1存入安全序列,并增加可用资源的值
此时的安全序列为:P1
3、然后重新从P0开始比对,发现还是不够;接下来是P2,同样不够;
直到P3,剩余资源满足P3的要求资源
此时的安全序列为:P1、P3
4、依此类推最终得到的安全序列为:P1、P3、P0、P2、P4
#include
#include
using namespace std;
// 定义函数:银行家算法
bool banker_algorithm(vector &available, vector> &max_request, vector> &allocation)
{
// 计算出需要的资源和已分配的资源
vector> need(max_request.size(), vector(max_request[0].size()));
for (int i = 0; i < allocation.size(); i++) {
for (int j = 0; j < allocation[0].size(); j++) {
need[i][j] = max_request[i][j] - allocation[i][j];
}
}
// 定义一些变量
vector finish(allocation.size(), false); // 用于标记每个进程是否完成
vector work(available); // 定义工作向量
// 实现银行家算法
while (true) {
// 在未完成的进程中查找一个满足条件的进程
int i = -1;
for (int k = 0; k < allocation.size(); k++) {
if (!finish[k]) {
bool can_allocated = true;
for (int j = 0; j < allocation[0].size(); j++) {
if (need[k][j] > work[j]) {
can_allocated = false;
break;
}
}
if (can_allocated) {
i = k;
break;
}
}
}
// 如果找不到满足条件的进程,则返回false表示不能进行资源分配
if (i == -1) {
return false;
}
// 更新工作向量和已完成的进程
for (int j = 0; j < allocation[0].size(); j++) {
work[j] += allocation[i][j];
}
finish[i] = true;
// 如果所有进程都已完成,则返回true表示可以进行资源分配
if (count(finish.begin(), finish.end(), true) == finish.size()) {
return true;
}
}
}
int main()
{
// 测试
vector available = {3, 3, 2};
vector> max_request = {
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3},
};
vector> allocation = {
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2},
};
if (banker_algorithm(available, max_request, allocation)) {
cout << "可以进行资源分配" << endl;
} else {
cout << "不能进行资源分配" << endl;
}
return 0;
}
1、我们有如下例子
2、我们观察P1连接的线,发现它在请求R2的一个资源;而R2此时恰好剩余一个资源,所以P1可以不会发生阻塞;而P2申请的R1资源已经被分配完了,所以P2会被阻塞。
3、当P1释放资源后,P2被唤醒,此时它也可以正常运行
4、当消除所有边后