Operating System - Deadlock Avoidance (Banker's Algorithm)



Read this chapter to learn how you can use the Banker's Algorithm to avoid a deadlock state in an operating system.

The Banker's Algorithm

The Banker's Algorithm is a deadlock avoidance algorithm that shows how to allocate resources to processes in a way that ensures that the system remains in a safe state. This works like a banker who allocates money to customers. Before allocating money to a customer, the banker must ensure that there is enough money in the bank to satisfy the maximum possible requests of all customers.

The Banker's Algorithm works in this way −

  • When a new process enters the system, it must declare the maximum number of instances of each resource type that it may need.
  • The OS then calculates whether allowing the request will leave the system in a safe state. If it does, the resources are allocated to the process.
  • If the request would lead to an unsafe state, it is not allowed to take any other resources too. The process must wait until some resources are released by other processes.

Steps for Banker's Algorithm

The Banker's Algorithm works in two main steps −

  • Safety Algorithm - Safe State Check
  • Resource Request Handling

Safety Algorithm

The safety algorithm is one that determines whether or not the system is in a safe state. A safe state is one where there is at least one sequence of processes such that each process can obtain its maximum resource request and complete its execution without leading to a deadlock.

The safety algorithm works as follows −

  • Initialize two vectors - Work and Finish. Set Work = Available and Finish [i] = FALSE for all processes.
  • Find an index "i" such that both - Finish [i] = FALSE and Need [i] ≤ Work. If no such "i" exists, go to step 4.
  • Set Work = Work + Allocation [i] and Finish [i] = TRUE. Go to step 2.
  • If Finish [i] = TRUE for all "i", then the system is in a safe state.

Resource Request Handling

When a process makes a request for resources, the Banker's Algorithm checks whether granting the request will leave the system in a safe state. The steps for handling a resource request are as follows −

  • If Request [i] ≤ Need [i], go to step 2. Otherwise, raise an error condition since the process has exceeded its maximum claim.
  • If Request [i] ≤ Available, go to step 3. Otherwise, the process must wait until resources are available.
  • Temporarily allocate the requested resources to process Pi by updating the following −
    • Available = Available - Request [i]
    • Allocation [i] = Allocation [i] + Request [i]
    • Need [i] = Need [i] - Request [i]
  • Use the safety algorithm to check if the system is in a safe state after the allocation. If it is, the request is granted. If not, roll back to the previous state and make the process wait.

Example of Banker's Algorithm

Consider a system with 5 processes (P0 to P4) and 3 resource types (A, B, C). The total resources in the system are −

  • Resource A: 10 instances
  • Resource B: 5 instances
  • Resource C: 7 instances

The current state of the system is represented by the following matrices −

Process Max Matrix Allocation Matrix Need Matrix
A B C A B C A B C
P0 7 5 3 0 1 0 7 4 3
P1 3 2 2 2 0 0 1 2 2
P2 9 0 2 3 0 2 6 0 0
P3 2 2 2 2 1 1 0 1 1
P4 4 3 3 0 0 2 4 3 1
  • Max Matrix − This contains the maximum resource needed for each process to complete its task.
  • Allocation Matrix − This contains the resources currently allocated to each process.
  • Need Matrix − This is calculated as Max - Allocation and represents the remaining resources needed by each process.

The Available resources in the system can be calculated as −

$$\mathrm{Available}_j \;=\; \mathrm{Total}_j \;-\; \sum_{i=0}^{n-1} \mathrm{Allocation}_{i,j} \qquad\text{for } j=0,\dots,m-1$$

So, Available = (10, 5, 7) - (7, 2, 5) = (3, 3, 2)

The Available resources are then used to check if the system is in a safe state after each allocation. If a process requests resources, the Banker's Algorithm will determine if granting the request will keep the system in a safe state.

The safe sequence for this example is - p1 → p3 → p4 → p0 → p2. This means that if the processes are executed in this order, all processes can complete their tasks without leading to a deadlock.

Implementation of Banker's Algorithm

The CPP code given below shows how to implement the Banker's Algorithm for deadlock avoidance in an operating system −

#include <iostream>
using namespace std;

#define P 5 // Number of processes
#define R 3 // Number of resources

int main() {
    int i, j, k;
    
    // Available resources
    int available[R] = {3, 3, 2};
    
    // Maximum resource demand of each process
    int max[P][R] = {
        {7, 5, 3},
        {3, 2, 2},
        {9, 0, 2},
        {2, 2, 2},
        {4, 3, 3}
    };
    
    // Resources currently allocated to each process
    int allocation[P][R] = {
        {0, 1, 0},
        {2, 0, 0},
        {3, 0, 2},
        {2, 1, 1},
        {0, 0, 2}
    };
    
    // Calculate the Need matrix
    int need[P][R];
    for (i = 0; i < P; i++) {
        for (j = 0; j < R; j++) {
            need[i][j] = max[i][j] - allocation[i][j];
        }
    }
    
    // Initialize Finish array
    bool finish[P] = {false};
    
    // Safe sequence array
    int safeSeq[P];
    int count = 0;
    
    // Banker's Algorithm
    while (count < P) {
        bool found = false;
        for (i = 0; i < P; i++) {
            if (!finish[i]) {
                bool canAllocate = true;
                for (j = 0; j < R; j++) {
                    if (need[i][j] > available[j]) {
                        canAllocate = false;
                        break;
                    }
                }
                if (canAllocate) {
                    for (k = 0; k < R; k++) {
                        available[k] += allocation[i][k];
                    }
                    safeSeq[count++] = i;
                    finish[i] = true;
                    found = true;
                }
            }
        }
        if (!found) {
            cout << "System is not in a safe state." << endl;
            return 0;
        }
    }
    
    cout << "System is in a safe state." << endl;
    cout << "Safe sequence is: ";
    for (i = 0; i < P; i++) {
        cout << "P" << safeSeq[i];
        if (i != P - 1) cout << " -> ";
    }
    cout << endl;
    return 0;
}

The output of the above code will be −

System is in a safe state.
Safe sequence is: P1 -> P3 -> P4 -> P0 -> P2

Conclusion

The Banker's Algorithm is a method to avoid deadlocks in an operating system. It works by calculating whether granting a resource request will not change the the safe state of the system. The resources are allocated only if the calculation shows that the system will remain in a safe state. So it is important to know the maximum resource needs of each process in advance to implement the Banker's Algorithm effectively.

Advertisements