您好,登錄后才能下訂單哦!
這篇文章給大家介紹Golang中怎么利用Goroutine控制并發,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
Channel
在 Golang 語言中,Channel 不僅可以用于協程之間通信,還可以使用 Channel 控制子協程,而且使用 Channel 實現并發控制比較簡單,比如以下示例,我們在 Golang 應用程序中啟動兩個協程,分別是主協程和子協程,主協程需要等待子協程運行結束后再退出程序。
示例代碼:
func main () { done := make(chan struct{}) go func() { fmt.Println("goroutine run over") done <- struct{}{} }() <- done fmt.Println("main goroutine run over") }
閱讀上面這段代碼,我們在子 goroutine 運行結束后,通過 Channel 通知主 goroutine 退出程序,實際上也可以反過來處理,主 goroutine 通知子 goroutine 退出程序,主 goroutine 向 channel 中發送數據,子 goroutine 等待接收 channel 中的數據。
如果在 Golang 應用程序中,需要讓主 goroutine 等待多個 goroutine 都運行結束后再退出程序,我們應該怎么實現呢?是的,同樣可以使用 Channel 實現,但是,有一個更優雅的實現方式,那就是 WaitGroup,顧名思義,WaitGroup 就是等待一組 goroutine 運行結束。
示例代碼:
func main () { wg := sync.WaitGroup{} wg.Add(10) for i := 0; i < 10; i++ { go func(id int) { fmt.Println(id, "運行結束") wg.Done() }(i) } wg.Wait() fmt.Println("main goroutine run over") }
閱讀上面這段代碼,我們啟動 10 個子 goroutine,主 goroutine 需要等待 10 個子 goroutine 都運行結束后再退出程序,我們使用的是 WaitGroup,它有三個方法,分別是 Add、Done 和 Wait,實際上 WaitGroup 維護了一個計數器,這三個方法都是圍繞這個計數器工作,Add 用于設置計數器的數值,Done 用于扣減計數器的數值,Wait 在計數器數值為 0 之前一直阻塞。關于 WaitGroup 的源碼解讀,在之前的文章中已介紹過,限于篇幅,這里就不再贅述。
Channel 和 WaitGroup 通常用于父子兩個層級的 goroutine 的應用程序的并發控制中,如果在 Golang 應用程序中,子協程繼續派生出協程,我們應該怎么控制呢?這種多級 goroutine 的應用程序,我們可以使用 Context 實現并發控制。
示例代碼:
func main() { ctx, cancel := context.WithCancel(context.Background()) go firstCtx(ctx) time.Sleep(5 * time.Second) fmt.Println("stop all sub goroutine") cancel() time.Sleep(5 * time.Second) } func firstCtx(ctx context.Context) { go secondCtx(ctx) for { select { case <-ctx.Done(): fmt.Println("first done") return default: fmt.Println("first running") time.Sleep(2 * time.Second) } } } func secondCtx(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("second done") return default: fmt.Println("second running") time.Sleep(2 * time.Second) } } }
閱讀上面這段代碼,在子協程 firstCtx 啟動子協程 secondCtx,主 goroutine 創建 context,并把 context 傳遞到所有子協程,然后主 goroutine 通過調用 cancle 停掉所有子協程。
關于Golang中怎么利用Goroutine控制并發就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。