問題由來:
如何在主協程裏面等待所有子協程執行完畢後再退出?
方案一(原始方法):用n個lock對應n和子協程
package main
import (
"fmt"
"sync"
"time"
)
func main() {
locks := []*sync.Mutex{}
lock1 := new(sync.Mutex)
lock1.Lock()
go doFunc(5, lock1)
locks = append(locks, lock1)
lock2 := new(sync.Mutex)
lock2.Lock()
go doFunc(8, lock2)
locks = append(locks, lock2)
lock3 := new(sync.Mutex)
lock3.Lock()
go doFunc(10, lock3)
locks = append(locks, lock3)
for _, lock := range locks {
lock.Lock()
}
fmt.Println("main go_rut finished")
}
func doFunc(job_id int, lock *sync.Mutex) {
for i := 0; i < job_id; i++ {
fmt.Println("doing job-->", job_id, i)
time.Sleep(3 * time.Second)
}
fmt.Println("job finished-->", job_id)
lock.Unlock()
}
這種寫法有一個問題:太羅嗦
方案二:WaitGroup
WaitGroup有三個重要操作:Add、Done、Wait,我們下面用實例看看怎麼用
package main
import (
"fmt"
"sync"
"time"
)
func main() {
group := new(sync.WaitGroup)
group.Add(1) //添加計數,可以是負數;計數器等於0將釋放wait;計數器爲負數,將panic
go doFunc(5, group)
group.Add(1)
go doFunc(8, group)
group.Add(1)
go doFunc(10, group)
group.Wait()
fmt.Println("main go_rut finished")
}
func doFunc(job_id int, grouo *sync.WaitGroup) {
for i := 0; i < job_id; i++ {
fmt.Println("doing job-->", job_id, i)
time.Sleep(3 * time.Second)
}
fmt.Println("job finished-->", job_id)
grouo.Done() //計數器減一
}
明顯簡潔很多!