3 回答

TA貢獻(xiàn)1765條經(jīng)驗(yàn) 獲得超5個(gè)贊
如果是
say("world")
go say("hello")
“world”調(diào)用必須在“hello” goroutine 啟動(dòng)之前完成?!癶ello” goroutine 沒有運(yùn)行或完成,因?yàn)?main 返回了。
為了
go say("world")
go say("hello")
goroutine 不會(huì)運(yùn)行或完成,因?yàn)?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貢獻(xiàn)1866條經(jīng)驗(yàn) 獲得超5個(gè)贊
恭喜你學(xué)習(xí)了 Go。作為一個(gè)新手,理解并發(fā)以及它與并行的不同是很好的。
并發(fā)
并發(fā)就像一個(gè)雜耍者用一只手在空中玩弄幾個(gè)球。無(wú)論他在玩多少個(gè)球,任何時(shí)候都只有一個(gè)球碰到他的手。
并行性
當(dāng)雜耍者開始用另一只手并行處理更多的球時(shí),我們有兩個(gè)并發(fā)進(jìn)程同時(shí)運(yùn)行。
Goroutines 很棒,因?yàn)樗鼈兗仁遣l(fā)又是自動(dòng)并行,這取決于可用的計(jì)算核心和GOMAXPROCS設(shè)置的變量。
單手雜耍者
回到單手、單核、并發(fā)雜耍者。想象一下,他以手為main套路,分別玩弄三個(gè)分別名為“hello”、“world”和“mars”的球。
var balls = []string{"hello", "world", "mars"}
func main() {
go say(balls[0])
go say(balls[1])
go say(balls[2])
}
或者更恰當(dāng)?shù)卣f(shuō),
func main() {
for _, ball := range balls {
go say(ball)
}
}
一旦三個(gè)球依次拋向空中,雜耍者只需立即收回手。也就是說(shuō),在main投出的第一個(gè)球甚至可以落在他的手上之前,例程就退出了。恥辱,球只是掉到了地上。糟糕的表演。
為了讓球回到他的手中,雜耍者必須確保他等待它們。這意味著他的手需要能夠跟蹤和計(jì)算他投出的球,并在每個(gè)球落地時(shí)學(xué)習(xí)。
最直接的方法是使用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很簡(jiǎn)單。當(dāng)一個(gè) goroutine 被生成時(shí),一個(gè)人添加到一個(gè)“積壓計(jì)數(shù)器”WaitGroup.Add(1)并調(diào)用WaitGroup.Done()以減少計(jì)數(shù)器。一旦 backlog 變?yōu)?0,就意味著所有 goroutine 都完成了,WaitGroup應(yīng)該停止等待(并抓住球!)。
雖然使用通道進(jìn)行同步很好,但鼓勵(lì)使用可用的并發(fā)工具,尤其是當(dāng)使用通道使代碼更加復(fù)雜和難以理解時(shí)。

TA貢獻(xiàn)1795條經(jīng)驗(yàn) 獲得超7個(gè)贊
那是因?yàn)閙ain函數(shù)已經(jīng)退出了。
當(dāng) main 函數(shù)返回時(shí),所有 goroutine 都會(huì)突然終止,然后程序退出。
你添加一個(gè)語(yǔ)句:
time.Sleep(100 * time.Second)
在 main 函數(shù)返回之前,一切順利。
但是在 Go 中一個(gè)好的做法是使用 channel,它用于在 goroutine 之間進(jìn)行通信。您可以使用它讓 main 函數(shù)等待后臺(tái) goroutines 完成。
- 3 回答
- 0 關(guān)注
- 218 瀏覽
添加回答
舉報(bào)