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

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

為什么這里有通道的可變輸出

為什么這里有通道的可變輸出

Go
慕萊塢森 2023-07-10 15:04:42
我創建 5 個通道并發送數據 5 次:package mainimport "fmt"func greet(c chan string) {? ? fmt.Println("Hello " + <-c + "!")}func main() {? ? fmt.Println("main() started")? ? c := make(chan string)? ? for i:=0; i<5; i++ {? ? ? ? go greet(c)? ? }? ? c <- "AAA"? ? c <- "BBB"? ? c <- "CCC"? ? c <- "DDD"? ? c <- "EEE"? ? fmt.Println("main() stopped")}我預計所有 5 個字符串都會被打印出來。但是,我發現輸出可變。一些輸出是:$ ./rnchannelmain() startedHello AAA!Hello DDD!Hello BBB!Hello CCC!Hello EEE!main() stopped$ ./rnchannelmain() startedHello CCC!Hello DDD!main() stopped$ ./rnchannelmain() startedHello CCC!Hello BBB!Hello AAA!Hello DDD!main() stopped為什么打印的行數可變?
查看完整描述

2 回答

?
繁花如伊

TA貢獻2012條經驗 獲得超12個贊

您不必等到打印完所有字符串才退出。一旦主線程到達執行結束,它就會關閉所有 goroutine 并結束程序。由于這種情況同時發生,因此無法確定將允許打印多少個字符串。



查看完整回答
反對 回復 2023-07-10
?
慕容3067478

TA貢獻1773條經驗 獲得超3個贊

當main()退出時,所有 goroutine 都會被殺死。無法保證您的其他 goroutine 會在此之前完成,這就是并發的本質。以下是修復方法。


首先,讓我們對 進行一些更改greet。讓其休眠一會兒,以使問題更加明顯。我們還將讓它接受字符串而不是通道,稍后我們就會明白原因。


func greet(str string) {

? ? time.Sleep(100 * time.Millisecond)

? ? fmt.Println("Hello " + str + "!")

}

我們不需要創建一堆 goroutine 從通道讀取固定次數,而是需要一個 goroutine 從通道讀取直到耗盡。使用 可以最簡單地完成此操作range。這充分利用了渠道的優勢。

我們還需要一種方法來告訴主程序等待循環完成。使用第二個通道最容易做到這一點。更復雜的同步使用WaitGroups。

c := make(chan string, 2)

done := make(chan bool, 1)

go func() {

? ? for str := range(c) {

? ? ? ? greet(str)

? ? }

? ? done <- true

}()

goroutine 會一直讀取c直到關閉。然后它會發送true到頻道done。兩者都經過緩沖,以避免由于阻塞等待讀取或寫入通道而導致死鎖。


回到main,我們寫入通道,顯式關閉它,然后等待從 讀取done。


? ? c <- "AAA"

? ? c <- "BBB"

? ? c <- "CCC"

? ? c <- "DDD"

? ? c <- "EEE"

? ? close(c)


? ? <-done

? ? fmt.Println("main() stopped")

<-done將阻塞,直到有東西可讀。這使得 goroutine 能夠完成。


并將它們整合在一起。


package main

import(

? ? "fmt"

? ? "time"

)

func greet(str string) {

? ? time.Sleep(100 * time.Millisecond)

? ? fmt.Println("Hello " + str + "!")

}

func main() {

? ? fmt.Println("main() started")

? ? c := make(chan string, 2)

? ? done := make(chan bool, 1)

? ? go func() {

? ? ? ? for str := range(c) {

? ? ? ? ? ? greet(str)

? ? ? ? }

? ? ? ? done <- true

? ? }()

? ? c <- "AAA"

? ? c <- "BBB"

? ? c <- "CCC"

? ? c <- "DDD"

? ? c <- "EEE"

? ? close(c)


? ? <-done

? ? fmt.Println("main() stopped")

}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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