2 回答

TA貢獻(xiàn)2012條經(jīng)驗(yàn) 獲得超12個(gè)贊
您不必等到打印完所有字符串才退出。一旦主線程到達(dá)執(zhí)行結(jié)束,它就會(huì)關(guān)閉所有 goroutine 并結(jié)束程序。由于這種情況同時(shí)發(fā)生,因此無(wú)法確定將允許打印多少個(gè)字符串。

TA貢獻(xiàn)1773條經(jīng)驗(yàn) 獲得超3個(gè)贊
當(dāng)main()退出時(shí),所有 goroutine 都會(huì)被殺死。無(wú)法保證您的其他 goroutine 會(huì)在此之前完成,這就是并發(fā)的本質(zhì)。以下是修復(fù)方法。
首先,讓我們對(duì) 進(jìn)行一些更改greet。讓其休眠一會(huì)兒,以使問(wèn)題更加明顯。我們還將讓它接受字符串而不是通道,稍后我們就會(huì)明白原因。
func greet(str string) {
? ? time.Sleep(100 * time.Millisecond)
? ? fmt.Println("Hello " + str + "!")
}
我們不需要?jiǎng)?chuàng)建一堆 goroutine 從通道讀取固定次數(shù),而是需要一個(gè) goroutine 從通道讀取直到耗盡。使用 可以最簡(jiǎn)單地完成此操作range
。這充分利用了渠道的優(yōu)勢(shì)。
我們還需要一種方法來(lái)告訴主程序等待循環(huán)完成。使用第二個(gè)通道最容易做到這一點(diǎn)。更復(fù)雜的同步使用WaitGroups。
c := make(chan string, 2)
done := make(chan bool, 1)
go func() {
? ? for str := range(c) {
? ? ? ? greet(str)
? ? }
? ? done <- true
}()
goroutine 會(huì)一直讀取c直到關(guān)閉。然后它會(huì)發(fā)送true到頻道done。兩者都經(jīng)過(guò)緩沖,以避免由于阻塞等待讀取或?qū)懭胪ǖ蓝鴮?dǎo)致死鎖。
回到main,我們寫入通道,顯式關(guān)閉它,然后等待從 讀取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")
}
- 2 回答
- 0 關(guān)注
- 160 瀏覽
添加回答
舉報(bào)