溫馨提示×

溫馨提示×

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

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

go并發(fā)中select的示例分析

發(fā)布時間:2021-11-17 17:56:01 來源:億速云 閱讀:300 作者:小新 欄目:大數(shù)據(jù)

這篇文章給大家分享的是有關(guān)go并發(fā)中select的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

一、前言介紹:

對于Go語言并發(fā)通訊,是使用的協(xié)程goroutine,而協(xié)程之間的通訊采用的是channel。但是channel不管是有緩存的,還是無緩存的都會有阻塞的情況出現(xiàn),只不過無緩存的阻塞會更加頻繁。而協(xié)程長時間阻塞了之后,Go語言本身又沒有提供這種超時的解決機制,所以開發(fā)者需要自己考慮實現(xiàn)這種超時機制。這種超時機制在Go語言中則是使用select來解決的。

相關(guān)的背景知識:

1.Go語言并發(fā)篇(一):之go語句篇:https://mp.weixin.qq.com/s/FD-MP9r5sEn1QYRAYZE_4g

2.Go語言之goroutine的調(diào)度原理:https://mp.weixin.qq.com/s/hTgIyJN7p-wrDfLj1bP1wQ

3.Go并發(fā)之channel篇:https://mp.weixin.qq.com/s/PIb-gGBootc6581pHhi5ew

二、Select內(nèi)容介紹

我們先來看幾個問題, select是什么?它都有哪n些特性?

語法定義:

select是Go語言中的一個控制語句,它有select,case, default共同構(gòu)成,與switch的書寫方式類似。

select只用來操作的channel的讀寫操作。

(備注:golang 的 select 本質(zhì)上,就是監(jiān)聽 IO 操作,當(dāng) IO 操作發(fā)生時,觸發(fā)相應(yīng)的動作。也是常用的多路復(fù)用的一種,例如poll, epoll(這個會在另外一個帖子中介紹), select )

例子:

go并發(fā)中select的示例分析

select 的特性:
1. 如果只有一個 case 語句評估通過,那么就執(zhí)行這個case里的語句

2. 如果有多個 case 語句評估通過,那么通過偽隨機的方式隨機選一個

3.如果 default 外的 case 語句都沒有通過評估,那么執(zhí)行 default 里的語句

4.如果沒有 default,那么 代碼塊會被阻塞,直到有一個 case 通過評估;否則一直阻塞

特性1:  select正常case能夠評估通過的例子:

go并發(fā)中select的示例分析

特性4: 沒有default分支,select被阻塞住的例子:

go并發(fā)中select的示例分析

對比特性1,會發(fā)現(xiàn),select在探測不到case是接收c1數(shù)據(jù)的情況下,會阻塞在哪里,不會打印"go end!"

特性3: 有default的例子:

go并發(fā)中select的示例分析

select存在default的話,在case不命中的情況下,會直接進(jìn)入default分支,協(xié)程一樣會結(jié)束,不會阻塞住。

特性2: 多個case 同時滿足的情況,會隨機選擇一個case

go并發(fā)中select的示例分析

通過輸出我們可以看出來,盡管channel c1和c2基本是同時寫的數(shù)據(jù)到channel中,但是select選擇了c2,忽略了c1。

三、select的應(yīng)用場景

 在看完了select的特性之后,筆者知道了channel的使用方式。可是到底什么時候使用select呢?于是筆者便問了自己另外一個問題。

select的應(yīng)用場景都有哪些,為什么我們需要select?

場景一:實現(xiàn)非阻塞讀寫操作。

根據(jù)select的特性3(如果 default 外的 case 語句都沒有通過評估,那么執(zhí)行 default 里的語句), 我們可以實現(xiàn)非阻塞的讀寫操作。

這種情況,一般是發(fā)生在服務(wù)器在給用戶推送數(shù)據(jù)之后,不希望用戶一直阻塞在讀操作上面。代碼實例參考特性3的例子,我們利用default來跳過這個阻塞過程。

場景二: 為請求設(shè)置超時時間。

這一個場景也就是前言介紹里面提到的協(xié)程通訊時候,長時間收不到讀寫操作,導(dǎo)致協(xié)程一直被阻塞的情況,而超時機制則是一個很常規(guī)的操作。我們來看下例子:

1.復(fù)現(xiàn)channel阻塞的例子:

go并發(fā)中select的示例分析

2.超時處理的例子:

go并發(fā)中select的示例分析

例子1,因為channel中沒有數(shù)據(jù)可讀,導(dǎo)致協(xié)程一直阻塞住,并沒有g(shù)o end的日志打印出來。

例子2, 雖然channel 中依然沒有數(shù)據(jù)可讀,但是我們實現(xiàn)了超時機制,在2s超時之后,select會觸發(fā)超時相關(guān)的channel,進(jìn)而結(jié)束協(xié)程go的阻塞,打印出go end日志。

場景三: 調(diào)度協(xié)程,控制其他協(xié)程的退出或者完成

在并發(fā)程序中,通常 main goroutine 將任務(wù)分給其它 goroutine 去完成,而自身只是起到調(diào)度作用。這種情況下,main goroutine無法知道 其它goroutine 任務(wù)是否完成,此時我們需要 done channel來協(xié)助完成。

例子為:

不實用done channel的方式,會發(fā)現(xiàn)main的goroutinue并不會等待其他的goroutine結(jié)束之后,才結(jié)束,也不知道其他的goroutiue何時結(jié)束。

go并發(fā)中select的示例分析

添加了done channel之后,main goroutinue可以等待其他的goroutinue結(jié)束之后,再結(jié)束。

go并發(fā)中select的示例分析

感謝各位的閱讀!關(guān)于“go并發(fā)中select的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI