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 关注
- 117 浏览
添加回答
举报