2 回答

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

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")
}
- 2 回答
- 0 關注
- 151 瀏覽
添加回答
舉報