中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Golang中怎么實現并發協程

發布時間:2021-06-21 16:25:31 來源:億速云 閱讀:230 作者:Leah 欄目:大數據

本篇文章給大家分享的是有關Golang中怎么實現并發協程,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

1:使用for-range退出

for-range是使用頻率很高的結構,常用它來遍歷數據,range能夠感知channel的關閉,當channel被發送數據的協程關閉時,range就會結束,接著退出for循環。

它在并發中的使用場景是:當協程只從1個channel讀取數據,然后進行處理,處理后協程退出。下面這個示例程序,當in通道被關閉時,協程可自動退出。

go func(in <-chan int) {
    // Using for-range to exit goroutine
    // range has the ability to detect the close/end of a channel
    for x := range in {
        fmt.Printf("Process %d\n", x)
    }
}(inCh)

2:使用,ok退出

for-select也是使用頻率很高的結構,select提供了多路復用的能力,所以for-select可以讓函數具有持續多路處理多個channel的能力。但select沒有感知channel的關閉,這引出了2個問題

  1. 繼續在關閉的通道上讀,會讀到通道傳輸數據類型的零值,如果是指針類型,讀到nil,繼續處理還會產生nil。

  2. 繼續在關閉的通道上寫,將會panic。

問題2可以這樣解決,通道只由發送方關閉,接收方不可關閉,即某個寫通道只由使用該select的協程關閉,select中就不存在繼續在關閉的通道上寫數據的問題。

問題1可以使用,ok來檢測通道的關閉,使用情況有2種。

第一種:如果某個通道關閉后,需要退出協程,直接return即可。示例代碼中,該協程需要從in通道讀數據,還需要定時打印已經處理的數量,有2件事要做,所有不能使用for-range,需要使用for-select,當in關閉時,ok=false,我們直接返回。

go func() {
    // in for-select using ok to exit goroutine
    for {
        select {
        case x, ok := <-in:
            if !ok {
                return
            }
            fmt.Printf("Process %d\n", x)
            processedCnt++
        case <-t.C:
            fmt.Printf("Working, processedCnt = %d\n", processedCnt)
        }
    }
}()

第二種:如果某個通道關閉了,不再處理該通道,而是繼續處理其他case,退出是等待所有的可讀通道關閉。我們需要使用select的一個特征:select不會在nil的通道上進行等待。這種情況,把只讀通道設置為nil即可解決。

go func() {
    // in for-select using ok to exit goroutine
    for {
        select {
        case x, ok := <-in1:
            if !ok {
                in1 = nil
            }
            // Process
        case y, ok := <-in2:
            if !ok {
                in2 = nil
            }
            // Process
        case <-t.C:
            fmt.Printf("Working, processedCnt = %d\n", processedCnt)
        }

        // If both in channel are closed, goroutine exit
        if in1 == nil && in2 == nil {
            return
        }
    }
}()

3:使用退出通道退出

使用,ok來退出使用for-select協程,解決是當讀入數據的通道關閉時,沒數據讀時程序的正常結束。想想下面這2種場景,,ok還能適用嗎?

  1. 接收的協程要退出了,如果它直接退出,不告知發送協程,發送協程將阻塞。

  2. 啟動了一個工作協程處理數據,如何通知它退出?

使用一個專門的通道,發送退出的信號,可以解決這類問題。以第2個場景為例,協程入參包含一個停止通道stopCh,當stopCh被關閉,case <-stopCh會執行,直接返回即可。

當我啟動了100個worker時,只要main()執行關閉stopCh,每一個worker都會都到信號,進而關閉。如果main()向stopCh發送100個數據,這種就低效了。

func worker(stopCh <-chan struct{}) {
    go func() {
        defer fmt.Println("worker exit")
        // Using stop channel explicit exit
        for {
            select {
            case <-stopCh:
                fmt.Println("Recv stop signal")
                return
            case <-t.C:
                fmt.Println("Working .")
            }
        }
    }()
    return
}

最佳實踐回顧

  1. 發送協程主動關閉通道,接收協程不關閉通道。技巧:把接收方的通道入參聲明為只讀,如果接收協程關閉只讀協程,編譯時就會報錯。

  2. 協程處理1個通道,并且是讀時,協程優先使用for-range,因為range可以關閉通道的關閉自動退出協程。

  3. ,ok可以處理多個讀通道關閉,需要關閉當前使用for-select的協程。

  4. 顯式關閉通道stopCh可以處理主動通知協程退出的場景。

以上就是Golang中怎么實現并發協程,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高平市| 黄陵县| 平舆县| 印江| 景泰县| 陵川县| 峨边| 沅江市| 五莲县| 花莲县| 日喀则市| 宁津县| 新津县| 基隆市| 海林市| 康定县| 右玉县| 广灵县| 苏尼特左旗| 隆回县| 甘孜县| 金阳县| 长沙市| 东明县| 永修县| 克什克腾旗| 平邑县| 萍乡市| 廊坊市| 江达县| 永兴县| 永年县| 永德县| 广德县| 南宫市| 武陟县| 敦化市| 天水市| 阳新县| 手机| 九江市|