使用多维数组模拟死锁

时间:2014-03-25 03:19:07

标签: java deadlock

我正在尝试编写死锁检测算法。我必须使用一个7x7数组,其中包含w,x,s和n' s。 w =等待资源,x =独占资源,n =不需要资源。行表示作业或进程,列表示资源。我将给出一个测试用例数组:

    String [][] grid = {{"w","n","x","x","x","n","n"},
                        {"x","w","n","n","n","x","n"},   
                        {"n","x","w","n","n","n","n"},   
                        {"n","n","n","n","n","n","x"},   
                        {"n","n","n","n","n","n","n"},   
                        {"n","n","w","n","n","n","w"},   
                        {"w","w","w","w","w","w","w"}};

正如您所看到的,死锁位于第0行,第1行和第2行之间.R0正在等待C0(资源1),但R1正在保持它。 R1正在等待C1(资源2),但R2正在等待它。 R2正在等待C2(资源3),但R0正在等待它。在视觉上,这是一个循环。

我的算法在行中搜索w和x的列,并将它们放在一维数组中。那部分有效。该数组应读取w x w x w x ...直到结束。 为了检查我们是否完成了一个循环,我会跟踪找到w和x的行的索引,并将它们放入另一个单维数组中。所以在这个例子中,第一个数组将读取w x w x w x ...而第二个数组将读取0 1 1 2 2 0 ... 一旦单维数组达到4的大小(由计数变量确定),我将检查第一个索引(array [0])和最后一个索引(array [count-1])。如果array [0]是' w'和数组[count-1]是' x'如果行索引相等,则检测到死锁。

我的算法在纸上工作,但不知何故我的数学错误我的第二个数组(WHI)索引第一次正确打印出来(0 1 1 2 2 0 ...)但如果我打印出WHI [0] (它应该总是0)它给了我1 2 5 5 6 6 6 6 ...

    public void printSingleArrays()
{
    String [] WH = new String[14];
    int [] WHI = new int[14];
    int count = 0;

    for (int a = 0; a < WH.length && a < WHI.length; a += 2)
        for (int i = 0; i < array.length ; i++)
            for (int j = 0; j < array[i].length ; j++)
            {
                if (array[i][j].equals("w"))
                {
                    WH[a] = array[i][j];
                    WHI[a] = i;

                    count++;

                    System.out.print(WH[a] + " ");
                    System.out.println(WHI[a] + " ");

                    for (int k = 0; k < array.length; k++)
                    {
                        if (array[k][j].equals("x"))
                        {
                            WH[a+1] = array[k][j];
                            WHI[a+1] = k;

                            System.out.print(WH[a+1] + " ");
                            System.out.print(WHI[a+1] + " ");

                            count++;

                            if (count >= 4)
                            {
                                System.out.print("Count is: " + count); // used for debugging
                                System.out.print(", First letter is: " + WH[0]);
                                System.out.println(", Index is: " + WHI[0]);
                            }
                            else
                                System.out.println();
                        }
                    }
                }
            }
    for (int m = 0; m < WH.length; m++)
    {
        System.out.print(WH[m] + " ");
    }
    System.out.println();
    for (int n = 0; n < WH.length; n++)
    {
        System.out.print(WHI[n] + " ");
    }
}

显然,需要构造函数和客户端类。我想知道当打印出WHI [0]时我的数组WHI如何变化?如果您需要更多资源或指导问题,请告诉我们!

1 个答案:

答案 0 :(得分:0)

以下是使用图解决问题的示例。

  • 首先通过迭代网格构建图形
  • 首先遍历每列(i)的所有行(j),它将找到拥有&#34; x&#34;和等待节点的人有&#34; w&#34;。
  • 然后将acquirer节点添加到每个等待节点的获取列表中。
  • 现在我们已经准备好了图表,只需通过dfs迭代图表来查找周期,看看节点是否已被访问过,如果先前访问过任何节点,那么它就是循环,这意味着它是一个死锁。
  • 现在在这种情况下,图表可以断开图表意味着所有节点都可能无法到达一个或多个节点。在这种情况下,我们可能需要跟踪在检测周期时访问了哪些节点,并查找未访问的节点的周期。

以下是代码:

package example;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class DeadlockDetection {
    static String [][] grid = {{"w","n","x","x","x","n","n"},
        {"x","w","n","n","n","x","n"},
        {"n","x","w","n","n","n","n"},
        {"n","n","n","n","n","n","x"},
        {"n","n","n","n","n","n","n"},
        {"n","n","w","n","n","n","w"},
        {"w","w","w","w","w","w","w"}};

    public static void main(String[] args) {
        System.out.println(isDeadlock());
    }


    public static class Node{
        int id;
        List<Node> acquirerNodes = new ArrayList<Node>();
        public Node(int id){
            this.id=id;
        }
    }

    public static boolean isDeadlock(){
        List<Node> nodes = new ArrayList<Node>();
        //Construct Graph
        for(int i=0; i< grid.length; i++){
            nodes.add(new Node(i));
        }
        for(int i=0; i<grid.length; i++){
            List<Node> waitingNodes = new ArrayList<Node>();
            Node acquirer = null;
            for(int j=0; j<grid.length; j++){
                if(grid[j][i].equals("w") ){
                    waitingNodes.add(nodes.get(i));
                } else if(grid[j][i].equals("x") ){
                    acquirer = nodes.get(i);
                }
                if(acquirer != null)
                    for(Node n: waitingNodes)
                        n.acquirerNodes.add(acquirer);
            }
        }
        //In case of non-strongly disconnected graph, we may need to traverse through all nodes.
        HashSet<Node> nodesFoundInGraph = new HashSet<Node>();
        for(int i=0; i< grid.length; i++){
            if(!nodesFoundInGraph.contains(nodes.get(i))){
                HashSet<Node> visited = new HashSet<Node>();
                if(isCycle(nodes.get(i), visited))
                    return true;
                nodesFoundInGraph.addAll(visited);
            }
        }
        return false;
    }

    public static boolean isCycle(Node node, Set<Node> visited){
        if(visited.contains(node)){
            return true;
        }
        visited.add(node);
        for(Node n: node.acquirerNodes){
            if(isCycle(n, visited)){
                return true;
            }
        }
        return false;
    }
}