第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

Goroutines、Channels 和死鎖

Goroutines、Channels 和死鎖

Go
梵蒂岡之花 2021-11-08 19:00:29
我試圖更多地了解 go 的通道和 goroutines,所以我決定制作一個(gè)小程序來(lái)計(jì)算文件中的單詞,由bufio.NewScanner對(duì)象讀?。簄CPUs := flag.Int("cpu", 2, "number of CPUs to use")flag.Parse()runtime.GOMAXPROCS(*nCPUs)    scanner := bufio.NewScanner(file)lines := make(chan string)results := make(chan int)for i := 0; i < *nCPUs; i++ {    go func() {        for line := range lines {            fmt.Printf("%s\n", line)            results <- len(strings.Split(line, " "))        }    }()}for scanner.Scan(){    lines <- scanner.Text()}close(lines)acc := 0for i := range results {      acc += i }fmt.Printf("%d\n", acc)現(xiàn)在,在我迄今為止發(fā)現(xiàn)的大多數(shù)示例中,lines和results通道都將被緩沖,例如make(chan int, NUMBER_OF_LINES_IN_FILE). 盡管如此,在運(yùn)行此代碼后,我的程序存在并顯示fatal error: all goroutines are asleep - deadlock!錯(cuò)誤消息?;旧衔业南敕ㄊ俏倚枰獌蓚€(gè)通道:一個(gè)將文件中的行與 goroutine 通信(因?yàn)樗梢允侨魏未笮?,我不喜歡認(rèn)為我需要在make(chan)函數(shù)調(diào)用中通知大小。其他通道將收集來(lái)自 goroutine 的結(jié)果,在主函數(shù)中我將使用它來(lái)計(jì)算累積結(jié)果。使用 goroutine 和通道以這種方式進(jìn)行編程的最佳選擇應(yīng)該是什么?任何幫助深表感謝。
查看完整描述

2 回答

?
慕的地8271018

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超4個(gè)贊

正如@AndrewN 指出的那樣,問(wèn)題是每個(gè) goroutine 都到達(dá)了它試圖發(fā)送到results通道的地步,但是這些發(fā)送將阻塞,因?yàn)閞esults通道沒(méi)有緩沖并且在for i := range results循環(huán)之前沒(méi)有從它們讀取任何內(nèi)容。你永遠(yuǎn)不會(huì)進(jìn)入那個(gè)循環(huán),因?yàn)槟闶紫刃枰瓿蒮or scanner.Scan()循環(huán),它試圖將所有的lines發(fā)送到lines通道,這是被阻塞的,因?yàn)?goroutines 永遠(yuǎn)不會(huì)循環(huán)回 ,range lines因?yàn)樗鼈儽豢ㄔ诎l(fā)送到results.


您可能會(huì)嘗試做的第一件事是將這些scanner.Scan()東西放在一個(gè) goroutine 中,以便可以立即開(kāi)始讀取results通道。但是,您將遇到的下一個(gè)問(wèn)題是知道何時(shí)結(jié)束for i := range results循環(huán)。您想要關(guān)閉results通道,但只有在原始 goroutine 完成讀取lines通道之后。您可以在關(guān)閉results頻道后立即關(guān)閉lines頻道,但是我認(rèn)為這可能會(huì)引入潛在的競(jìng)爭(zhēng),因此最安全的做法是在關(guān)閉results頻道之前等待原始兩個(gè) goroutine 完成:(操場(chǎng)鏈接):


package main


import "fmt"

import "runtime"

import "bufio"

import "strings"

import "sync"


func main() {

    runtime.GOMAXPROCS(2)


    scanner := bufio.NewScanner(strings.NewReader(`

hi mom

hi dad

hi sister

goodbye`))

    lines := make(chan string)

    results := make(chan int)


    wg := sync.WaitGroup{}

    for i := 0; i < 2; i++ {

        wg.Add(1)

        go func() {

            for line := range lines {

                fmt.Printf("%s\n", line)

                results <- len(strings.Split(line, " "))

            }

            wg.Done()

        }()

    }


    go func() {

        for scanner.Scan() {

            lines <- scanner.Text()

        }

        close(lines)

        wg.Wait()

        close(results)

    }()


    acc := 0

    for i := range results {

        acc += i

    }


    fmt.Printf("%d\n", acc)

}


查看完整回答
反對(duì) 回復(fù) 2021-11-08
?
白衣染霜花

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超10個(gè)贊

默認(rèn)情況下,go 中的通道是無(wú)緩沖的,這意味著您生成的匿名 goroutine 都不能發(fā)送到結(jié)果通道,直到您開(kāi)始嘗試從該通道接收。這不會(huì)在主程序中開(kāi)始執(zhí)行,直到scanr.Scan()完成填充線路通道......它被阻止執(zhí)行直到您的匿名函數(shù)可以發(fā)送到結(jié)果通道并重新啟動(dòng)它們的循環(huán)。僵局。

您的代碼中的另一個(gè)問(wèn)題,即使通過(guò)緩沖通道來(lái)微不足道地修復(fù)上述問(wèn)題,對(duì)于 i := range 結(jié)果也將在沒(méi)有更多結(jié)果輸入時(shí)死鎖,因?yàn)橥ǖ郎形搓P(guān)閉。

編輯:如果您想避免緩沖通道,這是一種潛在的解決方案。基本上,第一個(gè)問(wèn)題是通過(guò)一個(gè)新的 goroutine執(zhí)行發(fā)送到結(jié)果通道來(lái)避免的,允許行循環(huán)完成。第二個(gè)問(wèn)題(不知道何時(shí)停止讀取通道)可以通過(guò)在創(chuàng)建 goroutine 時(shí)對(duì)其進(jìn)行計(jì)數(shù)并在考慮到每個(gè) goroutine 時(shí)明確關(guān)閉通道來(lái)避免。用等待組做類似的事情可能會(huì)更好,但這只是展示如何無(wú)緩沖地執(zhí)行此操作的一種非??焖俚姆椒?。


查看完整回答
反對(duì) 回復(fù) 2021-11-08
  • 2 回答
  • 0 關(guān)注
  • 203 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)