golang select default continue_Go并发(四):select篇
原文鏈接:https://mp.weixin.qq.com/s/nJRVbhRQCgWHR1eHSfBpFA
一、前言介紹:
對于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_4g2.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是什么?它都有那些特性?
語法定義: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 )
例子:
select 的特性:1. 如果只有一個 case 語句評估通過,那么就執(zhí)行這個case里的語句
2. 如果有多個 case 語句評估通過,那么通過偽隨機的方式隨機選一個
3.如果 default 外的 case 語句都沒有通過評估,那么執(zhí)行 default 里的語句
4.如果沒有 default,那么 代碼塊會被阻塞,直到有一個 case 通過評估;否則一直阻塞
特性1: select正常case能夠評估通過的例子:
?特性4: 沒有default分支,select被阻塞住的例子:
對比特性1,會發(fā)現(xiàn),select在探測不到case是接收c1數(shù)據(jù)的情況下,會阻塞在哪里,不會打印"go end!"
特性3: 有default的例子:
select存在default的話,在case不命中的情況下,會直接進入default分支,協(xié)程一樣會結(jié)束,不會阻塞住。
特性2: 多個case 同時滿足的情況,會隨機選擇一個case
?通過輸出我們可以看出來,盡管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阻塞的例子:
?2.超時處理的例子:
?例子1,因為channel中沒有數(shù)據(jù)可讀,導(dǎo)致協(xié)程一直阻塞住,并沒有g(shù)o end的日志打印出來。
例子2, 雖然channel 中依然沒有數(shù)據(jù)可讀,但是我們實現(xiàn)了超時機制,在2s超時之后,select會觸發(fā)超時相關(guān)的channel,進而結(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é)束。
添加了done channel之后,main goroutinue可以等待其他的goroutinue結(jié)束之后,再結(jié)束。
?備注:對于select的實現(xiàn)機制,這個在后面的文章中介紹。
Go Channel 詳解: https://colobu.com/2016/04/14/Golang-Channels/
Go語言并發(fā)模型:使用 select:https://segmentfault.com/a/1190000006815341
灰子學(xué)技術(shù),歡迎關(guān)注,點評,相互學(xué)習(xí)。
?
總結(jié)
以上是生活随笔為你收集整理的golang select default continue_Go并发(四):select篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最近网络上爆出国内制造最贵武器?
- 下一篇: 俄罗斯SS-25导弹?