Go WaitGroup

問題由來:

如何在主協程裏面等待所有子協程執行完畢後再退出?

方案一(原始方法):用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() //計數器減一
}

明顯簡潔很多!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章