0{"/> 0{">

首頁 >後端開發 >Golang >致命錯誤:所有 goroutine 都在睡覺 - 死鎖!錯誤執行

致命錯誤:所有 goroutine 都在睡覺 - 死鎖!錯誤執行

王林
王林轉載
2024-02-10 16:42:191048瀏覽

致命错误:所有 goroutine 都在睡觉 - 死锁!错误执行

php小編草莓在這篇文章中將向大家介紹一個常見的程式錯誤:致命錯誤:「所有 goroutine 都在睡覺 - 死鎖!錯誤執行」。這是在Go語言中常見的錯誤之一,也是開發者經常遇到的挑戰之一。在本文中,我們將詳細解釋這個錯誤的原因和解決方法,幫助大家更好地理解和處理這個問題。無論是初學者還是有經驗的開發者,都能從本文中獲得有價值的資訊和技巧。讓我們一起來探索吧!

問題內容

我對 go 中的並發很陌生,所以我嘗試了一個帶有通道和 goroutine 的範例。我想要生產者-消費者模式。生產者函數永遠給出隨機字串,消費者透過將它們變為大寫來修改它們。我想在有限的時間(2 秒)內運行它。

package main

import (
    "fmt"
    "math/rand"
    "strings"
    "time"
)

func producer(x []string, c chan string) {
    i := 1
    for i > 0 {
        randomIndex := rand.Intn(len(x))
        pick := x[randomIndex]
        c <- pick
    }
}

func consumer(x string, c chan string) {
    x1 := strings.ToUpper(x)
    c <- x1
}

func main() {

    s := []string{"one", "two", "three", "four"}
    c1 := make(chan string)
    d1 := make(chan string)
    go producer(s, c1)
    go consumer(<-c1, d1)

    stop := time.After(2000 * time.Millisecond)
    for {
        select {
        case <-stop:
            fmt.Println("STOP AFTER 2 SEC!")
            return
        default:
            fmt.Println(<-d1)
            time.Sleep(50 * time.Millisecond)
        }
    }
}

我只收到一個陣列元素和一些錯誤。需要進行哪些更改才能使此範例正常運作?

輸出:

兩個

致命錯誤:所有 goroutine 都在休眠 - 死鎖!

goroutine 1 [chan receive]: main.main()

協程 6 [chan send]: main.生產者({0xc00004e040, 0x4, 0x0?}, 0x0?) 由 main 建立。主要的 退出狀態2

解決方法

您的消費者應該在循環中運行,這一點已經提到過。

更改consumer的第一個參數,使其為chan字串而不是字串。這樣生產者就可以不斷地向這個通道寫入數據,以便消費者在另一個通道上發布,直到時間限製到期。

func consumer(consumechan chan string, outch chan string) {
    for {
        select {
        case s := <- consumechan:
            s = strings.toupper(s)
            outch <- s
        }
    }
}

現在,在呼叫 go consumer() 之前的主函數中,您正在等待生產者對 c1 通道的第一個回應。不要這樣做,而是將 c1 通道作為第一個參數傳遞。

func main() {
    s := []string{"one", "two", "three", "four"}
    c1 := make(chan string)
    d1 := make(chan string)
    go producer(s, c1)
    go consumer(c1, d1)

    stop := time.After(2000 * time.Millisecond)
    for {
        select {
        case <-stop:
            fmt.Println("STOP AFTER 2 SEC!")
            return
        case response := <- d1:
            fmt.Println(response)
            time.Sleep(50 * time.Millisecond)
        }
    }
}

這應該顯示生產者在 c1 通道上連續寫入隨機數,以及消費者在 d1 通道上連續寫入所有大寫文本,直到 2 秒結束。

以上是致命錯誤:所有 goroutine 都在睡覺 - 死鎖!錯誤執行的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除