银行家算法 C# .NET 6 实现:5进程3资源并发模拟与安全性检测流程
2026/7/10 2:14:34 网站建设 项目流程

银行家算法在C#中的实现:5进程3资源并发模拟与安全性检测

1. 银行家算法核心原理

银行家算法是一种经典的死锁避免算法,由Edsger Dijkstra于1965年提出。其核心思想是通过模拟资源分配过程,确保系统始终处于安全状态,从而避免死锁发生。

算法主要依赖以下数据结构:

  • Available:长度为m的向量,表示每类资源的可用数量
  • Max:n×m矩阵,记录每个进程对每类资源的最大需求
  • Allocation:n×m矩阵,表示当前已分配给各进程的资源数量
  • Need:n×m矩阵,计算每个进程还需要的资源数量(Need = Max - Allocation)

算法执行流程分为两个关键阶段:

  1. 资源请求检查

    • 验证请求是否超过进程声明的最大需求(Need)
    • 检查系统当前是否有足够资源满足请求(Available)
  2. 安全性检查

    • 模拟分配后的系统状态
    • 寻找一个安全序列,使得所有进程都能顺利完成
// 银行家算法核心数据结构示例 public class BankerAlgorithm { private int[] Available; // 可用资源向量 private int[,] Max; // 最大需求矩阵 private int[,] Allocation;// 分配矩阵 private int[,] Need; // 需求矩阵 private int ProcessCount; // 进程数量 private int ResourceTypes;// 资源类型数量 // 计算Need矩阵 private void CalculateNeed() { for(int i=0; i<ProcessCount; i++) for(int j=0; j<ResourceTypes; j++) Need[i,j] = Max[i,j] - Allocation[i,j]; } }

2. C#实现架构设计

2.1 类结构设计

采用面向对象方式设计,主要包含以下核心类:

  1. BankerAlgorithm:算法主类
  2. Process:进程资源信息封装
  3. ResourceRequest:资源请求封装
  4. SafetyChecker:安全性检查器
// 进程资源信息类 public class Process { public int Id { get; } public int[] MaxResources { get; } public int[] Allocated { get; private set; } public int[] Needed => MaxResources.Zip(Allocated, (m,a) => m-a).ToArray(); public Process(int id, int[] max) { Id = id; MaxResources = max; Allocated = new int[max.Length]; } public void Allocate(int[] request) { for(int i=0; i<request.Length; i++) Allocated[i] += request[i]; } }

2.2 核心算法实现

安全性检查算法的关键实现:

public bool IsSafeState() { int[] work = (int[])Available.Clone(); bool[] finish = new bool[ProcessCount]; // 寻找可满足的进程 while(true) { bool found = false; for(int i=0; i<ProcessCount; i++) { if(!finish[i] && NeedLessThanWork(i, work)) { // 模拟进程完成,释放资源 for(int j=0; j<ResourceTypes; j++) work[j] += Allocation[i,j]; finish[i] = true; found = true; break; } } if(!found) break; } return finish.All(f => f); } private bool NeedLessThanWork(int pid, int[] work) { for(int i=0; i<ResourceTypes; i++) if(Need[pid,i] > work[i]) return false; return true; }

3. 并发模拟实现

3.1 多进程资源请求处理

模拟5个进程并发请求3类资源的场景:

public class ResourceSimulator { private BankerAlgorithm banker; private Queue<ResourceRequest> pendingRequests = new Queue<ResourceRequest>(); public void ProcessRequest(int pid, int[] request) { if(!banker.ValidateRequest(pid, request)) { Console.WriteLine($"非法请求:进程{pid}请求资源超过其最大需求"); return; } if(!banker.CheckResourceAvailable(request)) { pendingRequests.Enqueue(new ResourceRequest(pid, request)); Console.WriteLine($"资源不足,请求进入等待队列:进程{pid}"); return; } if(!banker.TryAllocate(pid, request)) { pendingRequests.Enqueue(new ResourceRequest(pid, request)); Console.WriteLine($"分配可能导致不安全状态,请求进入等待队列:进程{pid}"); } else { Console.WriteLine($"成功为进程{pid}分配资源"); CheckPendingRequests(); } } private void CheckPendingRequests() { while(pendingRequests.Count > 0) { var req = pendingRequests.Peek(); if(banker.TryAllocate(req.Pid, req.Request)) { pendingRequests.Dequeue(); Console.WriteLine($"从等待队列中为进程{req.Pid}分配资源"); } else { break; } } } }

3.2 资源分配状态可视化

实现资源分配状态的可视化输出:

public void PrintSystemStatus() { Console.WriteLine("\n当前系统资源分配状态:"); Console.WriteLine("进程\t最大需求\t已分配\t还需"); for(int i=0; i<ProcessCount; i++) { Console.Write($"P{i}\t"); PrintResourceArray(GetRow(Max,i)); Console.Write("\t"); PrintResourceArray(GetRow(Allocation,i)); Console.Write("\t"); PrintResourceArray(GetRow(Need,i)); Console.WriteLine(); } Console.Write("可用资源:"); PrintResourceArray(Available); Console.WriteLine("\n"); } private void PrintResourceArray(int[] arr) { Console.Write("["); for(int i=0; i<arr.Length; i++) { Console.Write(arr[i]); if(i < arr.Length-1) Console.Write(", "); } Console.Write("]"); }

4. 测试用例设计

4.1 安全状态测试

初始资源:

  • 可用资源:[10, 5, 7]
  • 5个进程的最大需求矩阵:
进程A类B类C类
P0753
P1322
P2902
P3222
P4433

测试步骤:

  1. P0请求[0,1,0]
  2. P1请求[2,0,0]
  3. P2请求[3,0,2]
  4. P3请求[2,1,1]
  5. P4请求[0,0,2]

4.2 不安全状态测试

在安全状态测试基础上: 6. P0请求[1,0,1] → 应进入等待队列 7. P1请求[2,0,2] → 可分配 8. P1释放所有资源 → 触发等待队列处理

4.3 边界条件测试

测试资源刚好满足临界条件的情况:

  • 初始可用资源:[3,3,2]
  • P0请求[3,3,2] → 系统进入临界状态
  • 任何额外请求都应进入等待

5. 安全性检测流程优化

5.1 检测算法优化

传统安全性检测算法时间复杂度为O(n²×m),可通过以下方式优化:

public bool OptimizedSafetyCheck() { int[] work = (int[])Available.Clone(); bool[] finish = new bool[ProcessCount]; int count = 0; // 按进程所需资源总量排序,优先检查需求小的进程 var orderedProcesses = Enumerable.Range(0, ProcessCount) .OrderBy(i => GetTotalNeed(i)) .ToList(); foreach(int i in orderedProcesses) { if(!finish[i] && NeedLessThanWork(i, work)) { for(int j=0; j<ResourceTypes; j++) work[j] += Allocation[i,j]; finish[i] = true; count++; i = -1; // 重新从头检查 } } return count == ProcessCount; } private int GetTotalNeed(int pid) { int sum = 0; for(int i=0; i<ResourceTypes; i++) sum += Need[pid,i]; return sum; }

5.2 并发请求处理策略

采用多线程模拟真实并发环境:

public void SimulateConcurrentRequests() { var requests = new List<(int pid, int[] request)> { (0, new[]{1,0,0}), (1, new[]{4,1,1}), (2, new[]{2,1,1}), (3, new[]{0,0,2}), (0, new[]{1,0,1}), (1, new[]{2,0,2}) }; Parallel.ForEach(requests, req => { lock(this) { Console.WriteLine($"进程{req.pid}发起资源请求..."); ProcessRequest(req.pid, req.request); PrintSystemStatus(); } }); }

6. 实际应用中的注意事项

  1. 资源释放处理

    public void ReleaseResources(int pid, int[] release) { // 验证释放量不超过已分配量 for(int i=0; i<ResourceTypes; i++) { if(release[i] > Allocation[pid,i]) throw new ArgumentException("释放量超过已分配量"); } // 释放资源 for(int i=0; i<ResourceTypes; i++) { Allocation[pid,i] -= release[i]; Available[i] += release[i]; Need[pid,i] += release[i]; } Console.WriteLine($"进程{pid}释放资源成功"); CheckPendingRequests(); }
  2. 死锁预防策略

    • 设置请求超时机制
    • 实现资源预分配检查
    • 提供手动干预接口
  3. 性能考量

    • 对于大规模系统,可采用分区检查策略
    • 实现增量式安全性检查
    • 考虑引入资源分配优先级

7. 扩展功能实现

7.1 动态资源管理

支持运行时动态添加/移除资源:

public void AddResource(int resourceType, int count) { if(resourceType < 0 || resourceType >= ResourceTypes) throw new ArgumentException("无效资源类型"); Available[resourceType] += count; Console.WriteLine($"已添加{count}个{resourceType}类资源"); CheckPendingRequests(); } public void RemoveResource(int resourceType, int count) { if(Available[resourceType] < count) throw new ArgumentException("移除量超过可用量"); Available[resourceType] -= count; Console.WriteLine($"已移除{count}个{resourceType}类资源"); }

7.2 资源分配历史记录

public class AllocationHistory { private List<AllocationRecord> records = new List<AllocationRecord>(); public void AddRecord(int pid, int[] request, bool success) { records.Add(new AllocationRecord( DateTime.Now, pid, request, success )); } public void PrintHistory() { Console.WriteLine("\n资源分配历史记录:"); Console.WriteLine("时间\t\t进程\t请求\t结果"); foreach(var r in records) { Console.Write($"{r.Timestamp:HH:mm:ss}\tP{r.Pid}\t"); PrintResourceArray(r.Request); Console.WriteLine($"\t{(r.Success?"成功":"等待")}"); } } }

8. 完整示例代码结构

项目目录结构建议:

BankerAlgorithm/ ├── Models/ │ ├── Process.cs │ ├── ResourceRequest.cs │ └── AllocationHistory.cs ├── Core/ │ ├── BankerAlgorithm.cs │ └── SafetyChecker.cs ├── Services/ │ └── ResourceSimulator.cs └── Program.cs

核心调用示例:

// 初始化银行家算法 var banker = new BankerAlgorithm( available: new[] {10, 5, 7}, max: new[,] { {7,5,3}, {3,2,2}, {9,0,2}, {2,2,2}, {4,3,3} } ); // 创建模拟器 var simulator = new ResourceSimulator(banker); // 执行测试用例 simulator.ProcessRequest(0, new[] {0,1,0}); simulator.ProcessRequest(1, new[] {2,0,0}); simulator.ProcessRequest(2, new[] {3,0,2}); simulator.ProcessRequest(3, new[] {2,1,1}); simulator.ProcessRequest(4, new[] {0,0,2}); simulator.ProcessRequest(0, new[] {1,0,1}); // 应进入等待 simulator.ProcessRequest(1, new[] {2,0,2}); // 可分配 simulator.ReleaseResources(1, new[] {4,1,3}); // 释放P1资源

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询