3 回答
TA贡献1765条经验 获得超5个赞
如果是
say("world")
go say("hello")
“world”调用必须在“hello” goroutine 启动之前完成。“hello” goroutine 没有运行或完成,因为 main 返回了。
为了
go say("world")
go say("hello")
goroutine 不会运行或完成,因为 main 返回。
使用sync.WaitGroup防止 main 在 goroutines 完成之前退出:
func say(wg *sync.WaitGroup, s string) {
defer wg.Done()
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go say(&wg, "world")
go say(&wg, "hello")
wg.Wait()
}
TA贡献1866条经验 获得超5个赞
恭喜你学习了 Go。作为一个新手,理解并发以及它与并行的不同是很好的。
并发
并发就像一个杂耍者用一只手在空中玩弄几个球。无论他在玩多少个球,任何时候都只有一个球碰到他的手。
并行性
当杂耍者开始用另一只手并行处理更多的球时,我们有两个并发进程同时运行。
Goroutines 很棒,因为它们既是并发又是自动并行,这取决于可用的计算核心和GOMAXPROCS设置的变量。
单手杂耍者
回到单手、单核、并发杂耍者。想象一下,他以手为main套路,分别玩弄三个分别名为“hello”、“world”和“mars”的球。
var balls = []string{"hello", "world", "mars"}
func main() {
go say(balls[0])
go say(balls[1])
go say(balls[2])
}
或者更恰当地说,
func main() {
for _, ball := range balls {
go say(ball)
}
}
一旦三个球依次抛向空中,杂耍者只需立即收回手。也就是说,在main投出的第一个球甚至可以落在他的手上之前,例程就退出了。耻辱,球只是掉到了地上。糟糕的表演。
为了让球回到他的手中,杂耍者必须确保他等待它们。这意味着他的手需要能够跟踪和计算他投出的球,并在每个球落地时学习。
最直接的方法是使用sync.WaitGroup:
import (
"fmt"
"time"
"sync"
)
var balls = []string{"hello", "world", "mars"}
var wg sync.WaitGroup
func main() {
for _, ball := range balls {
// One ball thrown
wg.Add(1)
go func(b string) {
// Signals the group that this routine is done.
defer wg.Done()
// each ball hovers for 1 second
time.Sleep(time.Duration(1) * time.Second)
fmt.Println(b)
// wg.Done() is called before goroutine exits
}(ball)
}
// The juggler can do whatever he pleases while the
// balls are hanging in the air.
// This hand will come back to grab the balls after 1s.
wg.Wait()
}
WaitGroup很简单。当一个 goroutine 被生成时,一个人添加到一个“积压计数器”WaitGroup.Add(1)并调用WaitGroup.Done()以减少计数器。一旦 backlog 变为 0,就意味着所有 goroutine 都完成了,WaitGroup应该停止等待(并抓住球!)。
虽然使用通道进行同步很好,但鼓励使用可用的并发工具,尤其是当使用通道使代码更加复杂和难以理解时。
TA贡献1795条经验 获得超7个赞
那是因为main函数已经退出了。
当 main 函数返回时,所有 goroutine 都会突然终止,然后程序退出。
你添加一个语句:
time.Sleep(100 * time.Second)
在 main 函数返回之前,一切顺利。
但是在 Go 中一个好的做法是使用 channel,它用于在 goroutine 之间进行通信。您可以使用它让 main 函数等待后台 goroutines 完成。
- 3 回答
- 0 关注
- 247 浏览
添加回答
举报
