操作系统死锁实验六

操作系统死锁实验六

一、实验目的

如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件那么该进程集合就是死锁的。产生死锁的必要条件:互斥;请求资源和保持已获得资源不释放;不可抢占;循环等待。

二、实验内容

1、修改实验五中生产者消费者代码,交换生产者的两个P 操作,设置适当初始值,制造死锁,观察现象。
2、制造死锁与解决死锁。两个线程,一个线程在互斥的临界区内打印偶数,另一个线程在互斥的临界区内打印奇数。

三、实验步骤

1、(1)制造死锁,修改生产者消费者程序,交换两条 P 操作,去掉 sleep 以加快执行速度,修改初始值为缓冲区已满。
在这里插入图片描述

(2) 编译运行,观察现象,运行停滞,等待数分钟也不继续往下执行,出现了死锁现象。
在这里插入图片描述

(3) 分析出现死锁的原因参看伪代码描述框图。(陈渝视频 10.3 节大概 17 分钟处至结尾有这个分析)
当缓冲区装满时,继续运行,假设生产者被调度,执行 P(mutex),锁住临界区,接着执行P(empty),对empty 减 1 操作,缓冲区满时empty=0,减 1 后变成-1,empty<0,生产者被阻塞等待唤醒。而消费者这边由于临界区锁着无法进入,消费者被阻塞,也就无法执行V(empty)唤醒生产者。生产者和消费者都被阻塞了,都等待对方的信号唤醒,死锁了。
在这里插入图片描述

2、
(1) 制造死锁,在主线程中调用函数 pthread_cancel 强制结束打印偶数的线程,如果线程结束时,正好处在临界区内,那么还没有释放临界区的锁,另外一个线程一直等待锁,而无法继续执行,而主线程一直等待子线程结束回收资源,僵持住了,出现了死锁。

(2) 编译运行观察现象在这里插入图片描述
在这里插入图片描述

(3) 解决死锁
在这里插入图片描述

(4) 编译运行观察现象:
在这里插入图片描述

四、心得总结
产生死锁的四个必要条件:

(1)互斥条件:一个资源每次只能被一个进程使用。

(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3)不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之

一不满足,就不会发生死锁。

死锁的解除与预防

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源,在系统运行过程中,对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配。因此,对资源的分配要给予合理的规划。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,可以介绍一下《操作系统》第四版汤小丹等人编著的C语言代码实现银行家算法。代码可以自行设置进程相关数据,显示安全序列,可以多次申请资源查看是否安全。以下是代码示例: ```c #include <stdio.h> #include <stdlib.h> #define N 100 #define M 100 int available[M], max[N][M], allocation[N][M], need[N][M], request[M], finish[N], work[M], safe[N]; int n, m, num = 0; void init() { int i, j; printf("请输入进程数n和资源种类数m:\n"); scanf("%d%d", &n, &m); printf("请输入每个进程最大需求矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%d", &max[i][j]); } } printf("请输入每个进程已分配矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%d", &allocation[i][j]); } } printf("请输入每个进程还需要矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { need[i][j] = max[i][j] - allocation[i][j]; } } printf("请输入每个资源可用数:\n"); for (i = 0; i < m; i++) { scanf("%d", &available[i]); } } void show() { int i, j; printf("进程数n=%d, 资源种类数m=%d\n", n, m); printf("每个进程最大需求矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf("%d ", max[i][j]); } printf("\n"); } printf("每个进程已分配矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf("%d ", allocation[i][j]); } printf("\n"); } printf("每个进程还需要矩阵:\n"); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf("%d ", need[i][j]); } printf("\n"); } printf("每个资源可用数:\n"); for (i = 0; i < m; i++) { printf("%d ", available[i]); } printf("\n"); } int safety() { int i, j, k, flag, count = 0; for (i = 0; i < n; i++) { finish[i] = 0; } for (i = 0; i < m; i++) { work[i] = available[i]; } while (count < n) { flag = 0; for (i = 0; i < n; i++) { if (finish[i] == 0) { for (j = 0; j < m; j++) { if (need[i][j] > work[j]) { break; } } if (j == m) { for (k = 0; k < m; k++) { work[k] += allocation[i][k]; } finish[i] = 1; safe[count] = i; count++; flag = 1; } } } if (flag == 0) { return 0; } } return 1; } void request_res() { int i, j, p; printf("请输入请求资源的进程编号:\n"); scanf("%d", &p); printf("请输入请求资源向量:\n"); for (i = 0; i < m; i++) { scanf("%d", &request[i]); } for (i = 0; i < m; i++) { if (request[i] > need[p][i]) { printf("请求资源大于进程还需要的资源!\n"); return; } if (request[i] > available[i]) { printf("请求资源大于系统可用的资源!\n"); return; } } for (i = 0; i < m; i++) { available[i] -= request[i]; allocation[p][i] += request[i]; need[p][i] -= request[i]; } if (safety() == 1) { printf("同意分配请求!\n"); } else { printf("拒绝分配请求!\n"); for (i = 0; i < m; i++) { available[i] += request[i]; allocation[p][i] -= request[i]; need[p][i] += request[i]; } } } int main() { int i; init(); show(); if (safety() == 1) { printf("系统是安全的!\n"); printf("安全序列为:"); for (i = 0; i < n; i++) { printf("%d ", safe[i]); } printf("\n"); } else { printf("系统是不安全的!\n"); } request_res(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值