本例來自于《go語言實戰(zhàn)》,從這個例題開始居触,我們不斷迭代,不斷優(yōu)化,做出我們想要的程序。
eg1:
'''
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start sub goroutines")
go func() {
for count :=0; count <3; count++{
for char:='a';char<'a'+26;char++{
fmt.Printf("%c",char)
}
}
wg.Done()
}()
go func() {
for count :=0; count <3; count++{
for char:='A';char<'A'+26;char++{
fmt.Printf("%c",char)
}
}
wg.Done()
}()
wg.Wait()
fmt.Println()
fmt.Println("main goroutine over")
}
'''
由于并發(fā)程序的緣故聘惦,導(dǎo)致結(jié)果每次都不一樣,輸出大致結(jié)果如下:
Start sub goroutines
ABCDEFGHIJKLMNOPQRSTUVWXabcdefghYZABCDEijklmnopqrFGHstuvwxyIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
main goroutine over
中間的匿名函數(shù)明顯的我們要提出來儒恋,做成一個獨立的函數(shù)善绎。那就這么干,看看會出現(xiàn)什么情況诫尽。
eg2:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start sub goroutines")
go printer('a',wg)
go printer('A',wg)
wg.Wait()
fmt.Println()
fmt.Println("main goroutine over")
}
func printer(prefix rune,wg sync.WaitGroup) {
go func() {
for count := 0; count < 3; count++ {
for char := prefix; char < prefix+26; char++ {
fmt.Printf("%c", char)
}
}
wg.Done()
}()
}
代碼看起來干凈多了禀酱,但是效果呢?我們看看運行結(jié)果牧嫉。
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc00004c088)
C:/Go/src/runtime/sema.go:56 +0x40
sync.(*WaitGroup).Wait(0xc00004c080)
C:/Go/src/sync/waitgroup.go:130 +0x6b
main.main()
E:/mygo/goaction/goRoutine/goroutine.go:15 +0x10e
Start sub goroutines
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzwxyzabcdefghijklmnopabcdefghqrstuvwijklmnoxyzpqrstuvwxyz
Process finished with exit code 2
what?怎么會這樣剂跟。我們仔細看看,通過E:/mygo/goaction/goRoutine/goroutine.go:15 +0x10e的提示酣藻,我們發(fā)現(xiàn)可以看到曹洽,問題出在wg.wait()。為什么臊恋?因為永遠等不到wg的計數(shù)為0. wg的計數(shù)器的減少是由 wg.done()完成的衣洁,這一句語法也沒有問題墓捻,問題在哪里呢抖仅?因為是值傳遞,不是應(yīng)用傳遞砖第,導(dǎo)致出現(xiàn)錯誤撤卢。把函數(shù)的形式參數(shù)修改為指針,調(diào)用的時候直接取wg的地址OK了梧兼。直接看代碼
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start sub goroutines")
go printer('a',&wg)
go printer('A',&wg)
wg.Wait()
fmt.Println()
fmt.Println("main goroutine over")
}
func printer(prefix rune,wg *sync.WaitGroup) {
go func() {
for count := 0; count < 3; count++ {
for char := prefix; char < prefix+26; char++ {
fmt.Printf("%c", char)
}
}
wg.Done()
}()
}
結(jié)果沒問題放吩。
這段代碼看起來沒問題了,如果我不想在每個子goroutine中輸出羽杰,而是要集中統(tǒng)一輸出結(jié)果又該怎么做呢渡紫?對于go語言到推,當(dāng)然要選擇channel.該怎么做呢?下回分解惕澎。