问题由来:
如何在主协程里面等待所有子协程执行完毕后再退出?
方案一(原始方法):用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() //计数器减一
}
明显简洁很多!