死锁II检测算法-针对单资源竞争

这次的死锁检测条件是每个进程要获取的资源都只有一个实例对象
因此可以定义一个死锁检测算法,使用资源分配图变形为等待图如下如可以看看

死锁II检测算法-针对单资源竞争_第1张图片
未命名文件.png

上图的资源分配图可以看到箭头指向的方向表示需要对应的资源
我们简化整个图为等待图也就是因为p1需要r1资源然后 r1现在被p2使用所以p1需要的等待p2 其他类似的

这样一个算法我们可以看出是如果等待图有环的的也就出现死锁了。
算得的思想就是形成一个等待图然后检测等待图是否有环来判断是不是出现死锁

根据算法的描述我们想到数据结构
有向图----整个问题的核心就转化为查找有向图是否有环或者找到图里面的环
关于图的基本的理论思想可以参考算法导论等数据去理解

问题分为以下几步
1.构造有向图结构
2.查找有向图里面的环

package main

import (
    "fmt"
    "strconv"
)

// 逻辑不是很严谨  越界的没考虑-- scanf

// 边节点结构
type EdgeTableNode struct {
    index         int            // 顶点索引
    weight        int            // 权重
    edgeTableNode *EdgeTableNode // 下一个临界点的指针
}

// 顶点的数据信息
type VertInfo struct {
    value int
    name  string
}

// 顶点节点
type VertNode struct {
    vertInfo      VertInfo //  定点的数据信息
    edgeTableNode *EdgeTableNode // 图的边用链表
}

type Graph struct {
    vertNum  int  // 顶点数目
    grapType uint8 //图的类型有向图  无向图 默认初始话的有向图 没考虑无向图
    edgeNum  int // 图有多少个边

    hasCircle bool // 是否有环
    allCircle [][]int  // 所有的环
    visted    []int // 是否被访问过 图遍历的时候用到

    vertNode []*VertNode // 图所有顶点
}

var arrayList []int

func NewGraph(vertNum int, edgeNum int, grapType uint8) *Graph {
    return &Graph{vertNum: vertNum, hasCircle: false, allCircle: [][]int{},
        visted: make([]int, vertNum), grapType: grapType,
        edgeNum: edgeNum, vertNode: []*VertNode{}}
}

// 只做了有向图的初始化
// 没考虑无向图
func (this *Graph) InitGrap() {
    // 顶点初始化
    for i := 0; i < this.vertNum; i++ {
        vert := &VertNode{}

        vert.vertInfo.value = i
        vert.vertInfo.name = "V" + strconv.Itoa(i)

        fmt.Println(*vert)

        this.vertNode = append(this.vertNode, vert)
    }

    // 边初始化
    var startVert int
    var endVert int
    var weight int
    var n int
    for i := 0; i < this.edgeNum; i++ {
        n, _ = fmt.Scanf("%d %d %d", &startVert, &endVert, &weight)

        fmt.Printf("%d %d %d\n", startVert, endVert, n)

        var edgeNode = this.vertNode[startVert].edgeTableNode
        if edgeNode == nil {
            tempNode := new(EdgeTableNode)
            tempNode.weight = weight
            tempNode.index = endVert
            tempNode.edgeTableNode = nil
            this.vertNode[startVert].edgeTableNode = tempNode
            continue
        }

        for edgeNode != nil {
            // 单链表尾插节点
            if edgeNode.edgeTableNode == nil {
                tempNode := new(EdgeTableNode)
                tempNode.weight = weight
                tempNode.index = endVert
                tempNode.edgeTableNode = nil
                edgeNode.edgeTableNode = tempNode
                break
            }

            edgeNode = edgeNode.edgeTableNode
        }
    }
}

func FindArray(arr []int, v int) int {
    for index, value := range arr {
        if v == value {
            return index
        }
    }

    return -1
}

func (this *Graph) PrintAllCircle() {
    fmt.Println("打印环")
    for _, sli := range this.allCircle {
        fmt.Println(sli)
    }
}

// 查找所有换
func (this *Graph) FindCircle() {
    // 初始化0 表示没有被查找过
    this.DfsCircle(0)
}

// 遍历查找环
func (this *Graph) DfsCircle(v int) {
    j := FindArray(arrayList, v)
    if j != -1 {
        this.hasCircle = true

        tempSlice := make([]int, len(arrayList)-j)
        copy(tempSlice, arrayList[j:])
        this.allCircle = append(this.allCircle, tempSlice)
        return
    }

    arrayList = append(arrayList, v)

    edge := this.vertNode[v].edgeTableNode
    for edge != nil {
        this.DfsCircle(edge.index)
        edge = edge.edgeTableNode
    }

    // 如果走到这里说明当前这个节点不是环路点
    // 移除掉
    arrayList = arrayList[0 : len(arrayList)-1]
}

func GrapTest() {
    var grap = NewGraph(4, 5, 1)
    grap.InitGrap()

    grap.FindCircle()
    grap.PrintAllCircle()

}

// 因为go test 好像没办法使用从标准输入获取数据所以赢了main
func main() {
  GrapTest()
}

你可能感兴趣的:(死锁II检测算法-针对单资源竞争)