日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

php小編百草在這篇文章中將解答一個常見問題:“使用 WaitGroups 和 Buffered Channels 的 Go 代碼中出現死鎖的原因是什么?”在Go語言中,WaitGroups和Buffered Channels是常用的并發編程工具。然而,有時候在使用它們的代碼中可能會遇到死鎖的情況。本文將深入探討出現死鎖的原因,并提供解決方案,幫助讀者避免這種問題的發生。無論你是初學者還是有一定經驗的Go開發者,本文都將為你提供有價值的信息。

問題內容

等待組、緩沖通道和死鎖

我的這段代碼會導致死鎖,但我不確定為什么。我嘗試在幾個不同的地方使用互斥鎖,關閉單獨的 go 例程內外的通道,但結果仍然相同。

我嘗試通過一個通道 (inputchan) 發送數據,然后從另一個通道 (outputchan) 讀取數據

package main

import (
    "fmt"
    "sync"
)

func listStuff(wg *sync.WaitGroup, workerID int, inputChan chan int, outputChan chan int) {
    defer wg.Done()

    for i := range inputChan {
        fmt.Println("sending ", i)
        outputChan <- i
    }
}

func List(workers int) ([]int, error) {
    _output := make([]int, 0)

    inputChan := make(chan int, 1000)
    outputChan := make(chan int, 1000)

    var wg sync.WaitGroup
    wg.Add(workers)

    fmt.Printf("+++ Spinning up %v workers\n", workers)
    for i := 0; i < workers; i++ {
        go listStuff(&wg, i, inputChan, outputChan)
    }

    for i := 0; i < 3000; i++ {
        inputChan <- i
    }

    done := make(chan struct{})
    go func() {
        close(done)
        close(inputChan)
        close(outputChan)
        wg.Wait()
    }()

    for o := range outputChan {
        fmt.Println("reading from channel...")
        _output = append(_output, o)
    }

    <-done
    fmt.Printf("+++ output len: %v\n", len(_output))
    return _output, nil
}

func main() {
    List(5)
}

登錄后復制

解決方法

主函數中的代碼是連續的,首先嘗試將 3k 值寫入 inputchan 然后將從 outputchan 讀取值。

您的代碼會在第一個步驟中阻塞:

在 3k 值成功發送到 inputchan 之前,outputchan 不會流失任何內容,因此工作人員最終會在第一個 1k 值之后卡在 outputchan <- i
一旦工作人員停止從 inputchan 中消耗資源,main 將在大約 2k 個值之后卡在 inputchan <- i

解決此問題的一種方法是讓生產者 (inputchan <- i) 和最終消費者 (for o := range outputchan {) 在單獨的 goroutine 中運行。

您可以將這些演員之一保留在主 goroutine 中,并為另一個演員旋轉一個新演員。例如:

go func(inputchan chan<- int){
    for i := 0; i < 3000; i++ {
        inputchan <- i
    }
    close(inputchan)
}(inputchan)

done := make(chan struct{})
go func() {
    close(done)
    // close(inputchan) // i chose to close inputchan above, don't close it twice
    close(outputchan)
    wg.wait()
}()

...

登錄后復制

https://www.php.cn/link/80e4c54699b5b8cf8c67dd496909fceb

一個額外的注意事項:圍繞發信號 done 的操作順序很重要;通道 doneoutputchan 只能在 wg.done() 指示所有工作人員完成后關閉

// it is best to close inputChan next to the code that controls
    // when its input is complete.
    close(inputChan)
    // If you had several producers writing to the same channel, you
    // would probably have to add a separate waitgroup to handle closing,
    // much like you did for your workers

    go func() {
        wg.Wait()
        // the two following actions must happen *after* workers have
        // completed
        close(done)
        close(outputChan)
    }()

登錄后復制

分享到:
標簽:Go語言
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定