如何找到死锁原因

问题描述 投票:-1回答:1

[我的任务是为Go中的过境点编写一个Trafficlight系统。因此,我们使用4个交通灯,它们应并行工作而不会引起任何死锁。

所以有北,南,西和东。一切都应以红色开头,然后:南北轴从红色变为绿色->黄色->红色。然后(以先到者为准)南北或东西向轴变为红色->绿色->黄色->红色..等。但是,我在(随机)时间或瞬间出现死锁。

这是我的Trafficlight功能:

func TL(direction CardinalDirections.CardinalDirection, comChannel chan string, syncChannel chan string) {

    fmt.Printf("initialisierung : " + direction.GetDirection())
    colour := Colours.Red // Zuerst sind alle Lichter auf Rot
    colour = direction.Init(comChannel, syncChannel) //start with the north south axis
    for {
        if colour == Colours.Red {
            fmt.Printf(direction.GetAchse()+": Waits\n")
            direction.Wait(comChannel, syncChannel) //  wait until syncChannel gets a signal
            colour = colour.ChangeColour(comChannel) //change to the next color
            fmt.Printf("Direction: %s Colour: %s\n", direction, colour)
        } else {
            colour = colour.ChangeColour(comChannel) //wechsle auf die nächste Farbe
            fmt.Printf("Direction: %s Colour: %s\n", direction, colour)
            if colour == Colours.Red {
                direction.ChangeAxis(comChannel, syncChannel)
            }
        }
    }
}

// init and go routines
func Start() {
    NorthSouthChannel := make(chan string)
    WestEastChannel := make(chan string)
    SyncChannel := make(chan string)

    //Starte alle go routinen
    go TL(CardinalDirections.North, NorthSouthChannel, SyncChannel)
    go TL(CardinalDirections.South, NorthSouthChannel, SyncChannel)
    go TL(CardinalDirections.West, WestEastChannel, SyncChannel)
    go TL(CardinalDirections.East, WestEastChannel, SyncChannel)

}

这是我的关联代码:

包装颜色

import "log"

type Colour string

const(
    Red    Colour = "red"
    Yellow        = "yellow"
    Green         = "green"
)

//This function allows two pocesses on the same axis to communicate and syncronies their colour

func (colour Colour) ChangeColour(ownChannel chan string) Colour {
    select {
    case msg := <-ownChannel:
        return Colour(msg)
    case ownChannel <- string(Suc(colour)):
        return Suc(colour)
    }
}

// Function that switches between the Colours

func Suc(colour Colour) Colour {
    switch colour {
    case Red:
        return Green
    case Green:
        return Yellow
    case Yellow:
        return Red
    default:
        log.Fatalf("Invalid Colour")
        return colour
    }
}

基本包装

import (
    "Trafficlight/Colours"
)


type CardinalDirection string

const(
    North CardinalDirection = "north"
    South                   = "south"
    West                    = "west"
    East                    = "east"
)

func (direction CardinalDirection) Wait(comChannel chan string, syncChannel chan string) {
    select {
    case msg := <-syncChannel: //wait if a signal comes from syncChannel
        if msg == direction.GetAchse() { // the message is the same Achse
            comChannel <- "start" // then send start to the other axis
        } else {
            syncChannel <- msg // otherwise send the message back
        }
    case msg := <-comChannel:
        if msg != "start" {
            comChannel <- msg // send the message again
        }
    }
}

func (direction CardinalDirection) Init(comChannel chan string, syncChannel chan string) Colours.Colour {
    if direction == North || direction == South {
        select {
        case msg := <-syncChannel:
            comChannel <- msg
            return Colours.Suc(Colours.Colour(msg))
        case msg := <-comChannel:
          return Colours.Suc(Colours.Colour(msg))
            return Colours.Suc(Colours.Colour(msg))
        }
    } else {
        select {
        case msg := <-comChannel:
            syncChannel <- msg
            return Colours.Colour(msg)
        case comChannel <- string(Colours.Red):
            return Colours.Red
        }
    }
}

// Function that switches between the CardinalDirections

func (direction CardinalDirection) Suc() CardinalDirection {
    switch direction {
    case North:
        return West
    case South:
        return East
    case West:
        return South
    case East:
        return North
    default:
        return direction
    }
}

// Function that assigns the CardinalDirections to their respective axex

func (direction CardinalDirection) GetAchse() string {
    switch direction {
    case North:
        return "north-south"
    case South:
        return "north-south"
    case West:
        return "west-east"
    case East:
        return "west-east"
    default:
        return ""
    }
}

func (direction CardinalDirection) GetDirection() string {
    switch direction {
    case North:
        return "north"
    case South:
        return "south"
    case West:
        return "west"
    case East:
        return "east"
    default:
        return "X"
    }
}

//This function allows two pocesses on the same axis to communicate, so they can give up the control at the same time.
//That way they can prevent, that a process from another axis changes the colour before all processes on their axis turned red.

func (direction CardinalDirection) ChangeAxis(comChannel chan string, syncChannel chan string) {
    select {
    case msg := <- comChannel:
        syncChannel <- msg
    case comChannel <- direction.Suc().GetAchse():
        return
    }
}

最后是我的主要功能。


import (
    "Trafficlight/TL"
    "fmt"
)

func main(){
    quitChannel := make(chan string)
    fmt.Printf("*** Start\n")
    TL.Start()
    fmt.Printf("*** Finish: %s\n", <- quitChannel)
}

这是终端中的错误消息。我得到:

...
north-south: Waits
west-east: Waits
north-south: Waits
Direction: south Colour: green
Direction: north Colour: green
Direction: north Colour: yellow
Direction: south Colour: yellow
Direction: south Colour: red
Direction: north Colour: red
north-south: Waits
north-south: Waits
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/main.go:12 +0xac

goroutine 6 [select]:
Trafficlight/Colours.Colour.ChangeColour(0x10d357f, 0x3, 0xc0000520c0, 0xc000052180, 0x0)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/Colours/Colours.go:16 +0xfc
Trafficlight/TL.TL(0x10d37a8, 0x5, 0xc0000520c0, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:19 +0x248
created by Trafficlight/TL.Start
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:38 +0xc6

goroutine 7 [chan send]:
Trafficlight/CardinalDirections.CardinalDirection.Wait(0x10d37c1, 0x5, 0xc0000520c0, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/CardinalDirections/CardinalDirections.go:23 +0x13e
Trafficlight/TL.TL(0x10d37c1, 0x5, 0xc0000520c0, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:18 +0x220
created by Trafficlight/TL.Start
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:39 +0x107

goroutine 8 [chan send]:
Trafficlight/CardinalDirections.CardinalDirection.Wait(0x10d3678, 0x4, 0xc000052120, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/CardinalDirections/CardinalDirections.go:21 +0x19b
Trafficlight/TL.TL(0x10d3678, 0x4, 0xc000052120, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:18 +0x220
created by Trafficlight/TL.Start
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:40 +0x148

goroutine 9 [chan send]:
Trafficlight/CardinalDirections.CardinalDirection.Wait(0x10d3640, 0x4, 0xc000052120, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/CardinalDirections/CardinalDirections.go:21 +0x19b
Trafficlight/TL.TL(0x10d3640, 0x4, 0xc000052120, 0xc000052180)
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:18 +0x220
created by Trafficlight/TL.Start
    /usr/local/Cellar/go/1.14/libexec/src/Trafficlight/TL/TL.go:41 +0x189

如何解决此死锁?我不知道这是代码问题还是算法问题。

go
1个回答
0
投票

不确定要提供什么OP代码作为信息,但是如果我只想知道当前选择了哪个方向,我会做得更简单。

package main

import (
    "fmt"
    "time"
)

func main() {

    tls := []string{
        "north-south",
        "west-east",
    }

    for {
        fmt.Println("waiting on", tls[0])
        <-time.After(time.Second)
        tls = append(tls[1:], tls[0])
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.