这次的死锁检测条件是每个进程要获取的资源都只有一个实例对象
因此可以定义一个死锁检测算法,使用资源分配图变形为等待图如下如可以看看
上图的资源分配图可以看到箭头指向的方向表示需要对应的资源
我们简化整个图为等待图也就是因为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()
}