Приоритетная очередь в GoLang с использованием каналов
На изображении выше - вопрос, который мне нужно решить. вот решение, которое я придумал (должно быть закодировано в Go). Я получаю ошибку тупика:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/kypriank/Assignment 5/priorityqueue.go:42 +0x1a3
goroutine 17 [chan send]:
main.priorityQueue(0xc420080060, 0xc4200800c0)
/home/kypriank/Assignment 5/priorityqueue.go:22 +0x1a2
created by main.main
/home/kypriank/Assignment 5/priorityqueue.go:40 +0xe5
exit status 2
Интересно, может ли кто-нибудь помочь мне выяснить, где мой код испортился (основная функция имеет некоторый код для проверки моего решения):
package main
var numOrder [20] int
var mesOrder [] PriorityMessage
var pri int
var a int
type PriorityMessage struct {
Priority int // between 0 and 9
Message string
}
func priorityQueue(west chan PriorityMessage, east chan string) {
incomming := <-west
if numOrder[incomming.Priority] == 10 {
numOrder[incomming.Priority] = incomming.Priority
}else {numOrder[incomming.Priority+1] = incomming.Priority}
mesOrder = append(mesOrder, incomming)
for i := 0; i < len(numOrder); i++ {if numOrder[i] != 10 {pri =
numOrder[i]; a = i; break}}
for i := 0; i < len(mesOrder); i++ {
if pri == mesOrder[i].Priority {
east <- (mesOrder[i]).Message
numOrder[a] = 10
mesOrder = append(mesOrder[:i], mesOrder[i+1:]...)
}
}
}
var west chan PriorityMessage
var east chan string
func printToScreen() {
for {println(<- east)}
}
func main() {
for i := 0; i < len(numOrder); i++ {numOrder[i] = 10}
west = make(chan PriorityMessage)
east = make(chan string)
go priorityQueue(west, east)
west <- PriorityMessage{1, "one"}
west <- PriorityMessage{0, "zero"}
west <- PriorityMessage{2, "two"}
west <- PriorityMessage{1, "another one"}
west <- PriorityMessage{0, "another zero"}
go printToScreen()
select {} // to allow all messages to be printed
}
1 ответ
Я действительно не смотрел на приоритетное поведение очереди, а вместо этого сосредоточился на тупике.
Итак, у вас есть несколько проблем, которые приведут вас в тупик:
- Вы только читаете из
west
один раз, однако вы пишете в него несколько раз. Это означает, что он будет блокироваться, когда вы пишетеzero
, Может быть, добавитьfor
петля. go printToScreen()
после всех писемwest
, Это означает, что когда вы идете рутинное чтение изwest
а затем писатьeast
попадает в часть записи, она блокируется, потому что ничего не читается изeast
,- Пустой выбор (
select{}
). В то время как это заблокирует основную рутинную процедуру, это будет происходить бесконечно. Это вызовет тупиковую панику, как только все остальные подпрограммы закроются.
Я изменил ваш код на это:
package main
import "time"
var numOrder [20]int
var mesOrder []PriorityMessage
var pri int
var a int
type PriorityMessage struct {
Priority int // between 0 and 9
Message string
}
func priorityQueue(west chan PriorityMessage, east chan string) {
for {
incomming := <-west
if numOrder[incomming.Priority] == 10 {
numOrder[incomming.Priority] = incomming.Priority
} else {
numOrder[incomming.Priority+1] = incomming.Priority
}
mesOrder = append(mesOrder, incomming)
for i := 0; i < len(numOrder); i++ {
if numOrder[i] != 10 {
pri =
numOrder[i]
a = i
break
}
}
for i := 0; i < len(mesOrder); i++ {
if pri == mesOrder[i].Priority {
east <- (mesOrder[i]).Message
numOrder[a] = 10
mesOrder = append(mesOrder[:i], mesOrder[i+1:]...)
}
}
}
}
var west chan PriorityMessage
var east chan string
func printToScreen() {
for {
println(<-east)
}
}
func main() {
for i := 0; i < len(numOrder); i++ {
numOrder[i] = 10
}
go printToScreen()
west = make(chan PriorityMessage)
east = make(chan string)
go priorityQueue(west, east)
west <- PriorityMessage{1, "one"}
west <- PriorityMessage{0, "zero"}
west <- PriorityMessage{2, "two"}
west <- PriorityMessage{1, "another one"}
west <- PriorityMessage{0, "another zero"}
time.Sleep(time.Hour)
}
И идут следующие результаты:
one
zero
two
another one
another zero