致命错误:所有goroutine都处于睡眠状态-再次发生死锁

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

我的骰子程序发生了一次严重的崩溃。它工作正常,但最后总是说:

致命错误:所有goroutine都在睡眠中-死锁!

goroutine 1 [chan接收]:main.main()/tärning.go:43+ 0x746

goroutine 6 [chan receive]:main.dice(0xc00003a0c0,0xc00003a120,0xc0000100a0)/tärning.go:51+ 0x106由main.main创建的/tärning.go:40+ 0x59a

goroutine 7 [chan接收]:main.dice(0xc00003a0c0,0xc00003a120,0xc0000100a0)/tärning.go:51+ 0x106由main.main创建的/tärning.go:41+ 0x5d3退出状态2

package main

import (
    "fmt"
    "sync"
    "math/rand"
)

type tärning struct {
    rubrik string
    minTal, maxTal int
}

type tärningsSvar struct {
    rubrik string
    svaret int
}

func main() {
    var wg sync.WaitGroup
    fmt.Println("Dags att kasta tärningar")
    var antal int
    fmt.Println("Hur många tärningar vill du använda?")
    fmt.Scan(&antal)
    job := make(chan tärning, antal)
    svar := make(chan tärningsSvar, antal)
    for i := 0; i < antal; i++ {
        fmt.Println("Vad ska tärning", i+1, "ha för rubrik?")
        var text string
        fmt.Scan(&text)
        fmt.Println("Vad ska vara minsta värdet på tärningen?")
        var minsta int
        fmt.Scan(&minsta)
        fmt.Println("Vad ska vara största värdet på tärningen?")
        var största int
        fmt.Scan(&största)
        job <- tärning{rubrik: text, minTal: minsta, maxTal: största}
    }
    go dice(job, svar, &wg)
    go dice(job, svar, &wg)
    wg.Wait()
    for svaren := range svar {
        fmt.Println("Tärning " + svaren.rubrik + " fick: ", svaren.svaret)
    }
}

func dice(job chan tärning, svar chan tärningsSvar, wg *sync.WaitGroup) {
    wg.Add(1) 
    for item := range job {
        text := item.rubrik
        min := item.minTal
        max := item.maxTal
        slump := (rand.Intn(max - min) + min)
        svar <- tärningsSvar{rubrik: text, svaret: slump}
    }
    wg.Done()
}
go deadlock
1个回答
2
投票

我已将您的代码固定在这里:https://play.golang.org/p/ZgRRb-wOdDk并附有注释。请检查。

您的代码中存在多个问题。1.您在代码中使用wg.Add(1)的方式将不起作用。您必须在开始执行go例程之前放入wg.Add(2),并从骰子功能中删除wg.Add(1),因为可能存在争用情况,并且当wg.Add(1)已经运行时,wg.Wait()可以运行。

  1. 您正在从事渠道工作。您没有关闭任何通道,而是尝试从该通道读取由于缓冲空间不足而该通道中可能没有数据的通道。因此,范围查询将被阻止。同时,您的svaren := range svar也将被阻止,因为没有人会向其中添加项目。因此,程序将陷入阻塞主功能以从svar通道读取数据的情况。并且dice功能被卡住,因为job通道中没有数据,并且在item := range job步骤中将其阻塞。

  2. 因此,如果两个go例程都互相等待,将导致死锁情况。

© www.soinside.com 2019 - 2024. All rights reserved.