亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

不生成相同的輸出并發 Go 工作線程池

不生成相同的輸出并發 Go 工作線程池

Go
素胚勾勒不出你 2022-10-04 19:33:16
我正在編寫一個程序,該程序從文本文件中逐字逐字讀取,以使用通道和工作線程池模式計算出現次數該程序在以程中工作:讀取文本文件(函數)readTextreadText函數將每個單詞發送到通道word每個戈魯丁執行對地圖中的單詞進行計數的函數countWord每個戈魯丁返回一個映射,工作器函數將結構的結果值傳遞給通道resultC測試函數根據來自通道的結果值創建映射resultC打印從步驟 5 創建的地圖該程序有效,但當我嘗試放置看到過程如下所示fmt.Println(0)func computeTotal() {    i := 0    for e := range resultC {        total[e.word] += e.count        i += 1        fmt.Println(i)    }}程序終止而不顯示/計算所有單詞1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 all goroutines finished 16 17 18 map[but:1 cat's:1 crouched:1 fur:1 he:2 imperturbable:1 it:1 pointed:1 sat:1 snow:1 stiffly:1 the:1 was:2 with:1] total words: 27 38 ... 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 Time taken for reading the book 5.8145ms如果我在此處的計算總計函數語句中取消注釋 fmt.println(), 程序將正確顯示結果,輸出如下所示all goroutines finishedmap[a:83 about:4 above:2 absolute:1 accepted:1 across:1 affection:1 after:1 again:5  wonder:2 wood:5 wooded:1 woody:1 work:1 worked:2 world:4 would:11 wrapped:1 wrong:1 yellow:2 yielded:1 yielding:1 counts continues ......]total words:  856Time taken for reading the book 5.9924ms這是我對閱讀文本的實現//ensure close words at the right timingfunc readText() {    file, err := os.Open(FILENAME)    if err != nil {        log.Fatal(err)    }    defer file.Close()    scanner := bufio.NewScanner(file)    scanner.Split(bufio.ScanWords)    for scanner.Scan() {        word := strings.ToLower(scanner.Text())        words <- strings.Trim(word, ".,:;")    }    //time.Sleep(1 * time.Second)    close(words)}這是我使用工人池的計數單詞實現//call countWord func,func workerPool() {    var wg sync.WaitGroup    for i := 1; i <= NUMOFWORKER; i++ {        wg.Add(1)        go worker(&wg)    }    wg.Wait()    fmt.Println("all goroutines finished")    close(resultC)}我一直在尋找為什么程序沒有顯示一致的結果,但我還無法弄清楚。如何對程序進行更改,使其產生相同的結果?
查看完整描述

2 回答

?
一只甜甜圈

TA貢獻1836條經驗 獲得超5個贊

該函數始終返回計數 == 1 的結果。countWord


下面是遞增計數的函數版本:


func countWord(word string, tempMap map[string]int) Result {

    count := tempMap[word] + 1

    tempMap[word] = count

    return Result{word, count}

}

但要抱住這個想法!該函數假定結果為 1。鑒于問題中的工人總是按預期發送,我們可以通過直接從發送來將工人從圖片中剔除。代碼如下:computeTotalcountResult{word, 1}computeTotalResult{word, 1}readText


func computeTotal() {

    i := 0

    for e := range resultC {

        total[e.word] += e.count

        i += 1

        fmt.Println(i)

    }

}


func readText() {

    file, err := os.Open(FILENAME)

    if err != nil {

        log.Fatal(err)

    }

    defer file.Close()

    scanner := bufio.NewScanner(file)

    scanner.Split(bufio.ScanWords)


    for scanner.Scan() {

        word := strings.ToLower(scanner.Text())

        resultC <- Result{strings.Trim(word, ".,:;"), 1}

    }

    close(resultC)

}


main() {

    ...

    go readText()

    computeTotal()

    fmt.Println(total)

    ...

}

通道操作的開銷可能否定了運行和單獨戈魯廷的任何好處。下面是組合成單個戈魯廷的代碼:computeTotalreadText


func main() {

    file, err := os.Open(FILENAME)

    if err != nil {

        log.Fatal(err)

    }

    defer file.Close()

    scanner := bufio.NewScanner(file)

    scanner.Split(bufio.ScanWords)


    var total = map[string]int{}

    for scanner.Scan() {

        word := strings.ToLower(strings.Trim(scanner.Text(), ".,:;"))

        total[word]++

    }

    fmt.Println(total)

}

問題中的函數使我認為您的目標是計算每個工人的單詞并合并結果以獲得總計。這是代碼:countWord


func computeTotal() {

    for i := 1; i <= NUMOFWORKER; i++ {

        m := <-resultC

        for word, count := range m {

            total[word] += count

        }

    }

}


func workerPool() {

    for i := 1; i <= NUMOFWORKER; i++ {

        go worker()

    }

}


func worker() {

    var tempMap = make(map[string]int)

    for w := range words {

        tempMap[w]++

    }

    resultC <- tempMap

}


...

var resultC = make(chan map[string]int)

...


func main() {

    ...

    go readText()

    workerPool()

    computeTotal()

    ...

}


查看完整回答
反對 回復 2022-10-04
?
四季花海

TA貢獻1811條經驗 獲得超5個贊

您必須通過以下方式重寫函數:computeTotal


func computeTotal(done chan struct{}) {

    defer close(done)

    i := 0

    for e := range resultC {

        total[e.word] += e.count

        i += 1

        fmt.Println(i)

    }

}


func main() {


   computeTotalDone := make(chan struct{})

   go computeTotal(computeTotalDone)

   ...

   workerPool() //blocking

   <-computeTotalDone

   fmt.Println(total)

}

添加會導致無效結果的原因是您的實現具有爭用條件。由于在主函數和函數中打印總結果并行運行,因此不能保證在調用之前處理所有消息。如果沒有該功能,您的計算機上的速度就足以產生正確的結果。fmt.Printlnfmt.Println(total)computeTotalcomputeTotalfmt.Println(total)fmt.PrintlncomputeTotal


建議的解決方案可確保在調用之前完成。computeTotalfmt.Println(total)


查看完整回答
反對 回復 2022-10-04
  • 2 回答
  • 0 關注
  • 142 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號