91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

golang?select機制和超時問題怎么解決

發布時間:2022-07-06 14:23:30 來源:億速云 閱讀:241 作者:iii 欄目:開發技術

這篇文章主要介紹了golang select機制和超時問題怎么解決的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇golang select機制和超時問題怎么解決文章都會有所收獲,下面我們一起來看看吧。

golang 中的協程使用非常方便,但是協程什么時候結束是一個控制問題,可以用 select 配合使用。

子協程和父協程的通信通常用 context 或者 chan。我遇到一個通常的使用場景,在子協程中嘗試多次處理,父協程等待一段時間超時,我選擇用 chan 實現。我以為 select 和 C++ 中 switch 類似,所以最開始代碼類似如下:

for {
    select {
        case <-ctx.Done():
            // process ctx done
        case <-time.After(time.Second * 3):
            // process after
        default:
            // process code
    }
}

測試發現無法實現 timeout,又仔細查看文檔,才發現 golang 中 select 另有玄機。廢話少說,直接總結要點:

  • select 中的 case 必須是進行 chan 的手法操作,也就是只能在 case 中操作 chan,并且是 非阻塞接收 。

  • select 中的 case 是同時監聽的,多個 case 同時操作,并未 switch 中一個個順序判斷。如果多個 case 滿足要求,隨機執行一個,如果一個沒有則阻塞當前的協程(沒有 default 情況下)。 很類似 Linux 文件符操作的 select 語義 。

  • 上面說的阻塞是沒有 default 的情況下,如果有 default,則執行 default,然后退出 select,也就是不會阻塞當前協程。

回到上述代碼,我這個 select 會一直不斷的執行 default, time.After 生成的 chan 并不會被阻塞判斷,所以根本無法完成我想要的效果。理解了之后重新修改代碼:

done := make(char int)
go func(c chan int) {
    for {
        // process code
        if {
            c <- 1
            return
        }
    }
    c <- 0
}(done)

select {
    case <-ctx.Done():
        // process ctx done
    case <-time.After(time.Second * 3):
        // process after
    case <-done:
        // process code
}

開一個新的協程去不斷嘗試,在外的三個 case 有一個滿足,則會執行。但是這里有一個問題非常需要注意: 子協程什么時候退出? 。

因為 gorountine 不能被強制 kill,所以在上述超時的情況下,select 語句執行 case time.After 之后退出, done 這個 chan 已經沒有接受方了,因此既沒有接受者,又沒有緩沖區,結合 chan 的特性,則子協程會一直阻塞無法退出,所以本質上這個實現會導致子協程累積下去,也就是 協程泄露 ,可能會使資源耗盡。

如何避免上述問題呢?一個很簡單的想法就是提供緩沖區, done := make(char int, 1) ,這樣即使沒有接收方,子協程也能完成發送,不會被阻塞。

還要一種辦法,上面說了,select 操作 chan,并且可以指定 default,那是不是有思路了呢?

if {
    select {
        case done <- 1:
        default:
            return
    }
}

關于“golang select機制和超時問題怎么解決”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“golang select機制和超時問題怎么解決”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

汨罗市| 当阳市| 阿勒泰市| 四会市| 老河口市| 韶山市| 北票市| 渭源县| 历史| 东兰县| 都昌县| 行唐县| 洛阳市| 策勒县| 太原市| 商城县| 类乌齐县| 吉首市| 红桥区| 建宁县| 长武县| 江都市| 云浮市| 太白县| 江孜县| 文山县| 通渭县| 永胜县| 贵德县| 清涧县| 射洪县| 钟山县| 寿宁县| 北票市| 台湾省| 武冈市| 南皮县| 长垣县| 杂多县| 文山县| 沛县|