Go並發控制--Channel篇


1. 前言

我們考慮這么一種場景,協程A執行過程中需要創建子協程A1、A2、A3…An,協程A創建完子協程后就等待子協程退出。
針對這種場景,GO提供了三種解決方案:

  • Channel: 使用channel控制子協程
  • WaitGroup : 使用信號量機制控制子協程
  • Context: 使用上下文控制子協程

三種方案各有優劣,比如Channel優點是實現簡單,清晰易懂,WaitGroup優點是子協程個數動態可調整,Context優點是對子協程派生出來的孫子協程的控制。
缺點是相對而言的,要結合實例應用場景進行選擇。


channel一般用於協程之間的通信,channel也可以用於並發控制。比如主協程啟動N個子協程,主協程等待所有子協程退出后再繼續后續流程,這種場景下channel也可輕易實現。


2. 使用channel控制子協程


2.1 使用場景

package main

import (
    "time"
    "fmt"
)

func Process(ch chan int) {
    //Do some work...
    time.Sleep(time.Second)

    ch <- 1 //管道中寫入一個元素表示當前協程已結束
}

func main() {
    channels := make([]chan int, 10) //創建一個10個元素的切片,元素類型為channel

    for i:= 0; i < 10; i++ {
        channels[i] = make(chan int) //切片中放入一個channel
        go Process(channels[i])      //啟動協程,傳一個管道用於通信
    }

    for i, ch := range channels {  //遍歷切片,等待子協程結束
        <-ch
        fmt.Println("Routine ", i, " quit!")
    }
}

上面程序通過創建N個channel來管理N個協程,每個協程都有一個channel用於跟父協程通信,父協程創建完所有協程后等待所有協程結束。


這個例子中,父協程僅僅是等待子協程結束,其實父協程也可以向管道中寫入數據通知子協程結束,這時子協程需要定期地探測管道中是否有消息出現。


2.2 總結

使用channel來控制子協程的優點是實現簡單,缺點是當需要大量創建協程時就需要有相同數量的channel,而且對於子協程繼續派生出來的協程不方便控制。

下一篇介紹 並發控制--WaitGroup篇


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM