赞
踩
在课程已经学习了死锁的4个必要条件的基础上,为了了解系统的资源分配情况,假定系统中任一资源在每一时刻只能由一个进程使用,任何进程不能抢占其它进程正在占有的资源,当进程得不到资源时,必须等待。因此,只要资源分配策略能保证不出现循环等待,系统就不会发生死锁。
要求学生编写和调试系统动态分配资源的仿真程序,观察死锁产生的条件,再采用适当的算法,有效地防止和避免死锁发生。
PS:实体类使用lombox自动生成getter setter 有参 无参方法(没有的手动生成)
lombox maven仓库地址
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
随机分配算法产生死锁,银行家算法避免死锁
随机分配算法:此算法不是模拟死锁而是会真正产生死锁(多运行几次随机的有的时候不会产生死锁)
package com.xu.demo.ytu.bank; import java.util.ArrayList; import java.util.List; public class RandomAgl { public static Object A=new Object(); public static Object B=new Object(); public static Object C=new Object(); public static Object D=new Object(); public static void RanDomTest(List<Object> list){ System.out.println(list); new Thread(()->{ synchronized (A){ System.out.println(Thread.currentThread().getName()+"我得到了资源:"+A); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Object O=list.get((int) (Math.random() * 4)); System.out.println("随机分配资源开始:线程"+Thread.currentThread().getName()+"随机去获取的资源是"+O); synchronized (O){ System.out.println("线程"+Thread.currentThread().getName()+"得到了资源"+O); } } }).start(); new Thread(()->{ Object O=list.get((int) (Math.random() * 4)); synchronized (B){ System.out.println(Thread.currentThread().getName()+"我得到了资源:"+B); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("随机分配资源开始:线程"+Thread.currentThread().getName()+"随机去获取的资源是"+O); synchronized (O){ System.out.println("线程"+Thread.currentThread().getName()+"得到了资源"+O); } } }).start(); } public static void main(String[] args) { List<Object> testList=new ArrayList<>(); testList.add(A); testList.add(B); testList.add(C); testList.add(D); RandomAgl.RanDomTest(testList); } }
运行截图
死锁已经产生,接下来进入java的bin目录具体查看
可以看出,线程1得到了资源270ca0并且想要去获取资源270c90,线程0得到了资源270c90并且想要获取资源270ca0死锁产生
银行家算法:
PCB类
package com.xu.demo.ytu.bank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class PCB { String processName; int maxUsed; int alreadyUsed; boolean isFinish; @Override public String toString() { return "\t"+processName + " \t" + maxUsed + " \t" + alreadyUsed + " \t" +(maxUsed-alreadyUsed)+ " \t" + isFinish ; } }
BankAlg
package com.xu.demo.ytu.bank; import java.util.*; public class BankAlg { public static int availableSource = 10; public static ArrayList<String> safeList = new ArrayList<>(); public static Map<String, PCB> pcbMap = new LinkedHashMap<>(); /** * 初始化操作 */ public static void init() { PCB a = new PCB("A", 5, 1, false); PCB b = new PCB("B", 3, 1, false); PCB c = new PCB("C", 4, 2, false); PCB d = new PCB("D", 6, 3, false); pcbMap.put(a.processName, a); pcbMap.put(b.processName, b); pcbMap.put(c.processName, c); pcbMap.put(d.processName, d); System.out.println("---------------------------------------初始化--------------------------------------------------"); System.out.println("进程名 " + "最大需求量 " + "占有量 " + " 仍需 " + " 完成"); pcbMap.forEach((k, v) -> { System.out.println(v); }); pcbMap.forEach((k, v) -> { availableSource -= v.alreadyUsed; }); System.out.println("剩余资源量:" + availableSource); } /** *安全性检测算法 */ public static void safe(String pName, int pNum) { //请求的资源大于剩余资源,请求不安全,拒绝分配 if (availableSource < pNum) { System.out.println("请求不安全 拒绝分配"); } else { //尝试分配 availableSource = availableSource - pNum; pcbMap.get(pName).alreadyUsed += pNum; //仍需资源如果为0,表明进程请求资源结束,进程释放资源 if (pcbMap.get(pName).maxUsed - pcbMap.get(pName).alreadyUsed == 0) { availableSource += pcbMap.get(pName).maxUsed; pcbMap.get(pName).isFinish = true; pcbMap.get(pName).maxUsed = pcbMap.get(pName).alreadyUsed = 0; } //添加安全序列 pcbMap.forEach((k, v) -> { if (v.maxUsed - v.alreadyUsed <= availableSource && !v.isFinish) { safeList.add(k); } }); //如果安全队列没有满,就说明当前分配资源可能不安全,继续尝试 //找不到安全序列,拒绝请求 if (safeList.size() == 0) { List<Boolean> checkList = new ArrayList<>(); pcbMap.forEach((k, v) -> { checkList.add(v.isFinish); }); //如果安全序列全部完成不进行撤销 System.out.println("请求不安全 拒绝分配"); availableSource = availableSource + pNum; pcbMap.get(pName).alreadyUsed -= pNum; //这种情况比较特殊这时候对最后一个进程完成分配 if (!checkList.contains(false)) { availableSource = availableSource - pNum; pcbMap.get(pName).alreadyUsed += pNum; } } //继续尝试分配 int temp = 0; for (String s : safeList) { //在已经添加到安全序列的进程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。