Go併發程式設計 select的使用

2021-08-22 08:25:37 字數 2223 閱讀 4620

本文描述了select的用法,通過select可以監聽多個channel的讀寫事件。這很類似於linux系統程式設計的select函式。但在go中,實現的機制明顯是不同的。linux系統程式設計的select是輪訓的機制,而且監控的是檔案描述符,且有數量的限制。go中的select和channel配合使用,監控的是channel的讀寫狀態。

var c1, c2 <-chan

inte***ce{}

var c3 chan

<- inte***ce{}

select {}: //監控channel的寫事件

// do something

}

func testselect1() )

go func() ()

fmt.println("blocking on read...")

select

}

注意:當close channel時,讀取channel的一方會從channel中讀取到value,false,此時的value一般情況下為nil。

該例子也可以用來通知當不使用channel時,關閉channel的情況。

當多個channel同時準備好,select的行為是怎樣的呢?我們通過乙個例子來看一下:

func testmultichannel() ); close(c1)

c2 := make(chan

inte***ce{}); close(c2)

c3 := make(chan

inte***ce{}); close(c3)

var c1count, c2count, c3count int

for i :=1000; i >=0; i--

}fmt.printf("c1count: %d\nc2count: %d\nc3count: %d\n", c1count, c2count, c3count)

}

輸出:

c1count: 337

c2count: 319

c3count: 345

多執行幾次,可以看出,幾個數字相差都不是很大。

以上例子,同時有3個channel可讀取,從以上的輸出可以看出,select對多個channel的讀取排程是基本公平的。讓每乙個channel的資料都有機會被處理。

在很多情況下,當channel沒有準備好時,我們希望能夠設定乙個超時時間,並在等待channel超時時進行一些處理。此時就可以按以下方式來進行編碼:

func testproctimeout() 

}}

該**會每隔1秒鐘,列印出:

timed out.do something.

timed out.do something.

timed out.do something.

...

這樣select就變成了「非阻塞」模式,我們可以設定乙個時間,當沒有channel可處理時,可以處理超時時間。這也是後台伺服器程式設計常用的處理方式。

當沒有任何channel準備好資料時,可以設定是執行預設的處理**。

func testdefaultproc() 

}

注意:default和處理超時不同,當沒有channel可讀取時,會立即執行default分支。而超時的處理,必須要等到超時,才處理。

func testexitloop() )

gofunc() ()

workcounter :=0

loop:

for

// simulate work

workcounter++

time.sleep(1*time.second)

}fmt.printf("在通知退出迴圈時,執行了%d次.\n", workcounter)

}

啟動乙個goroutine,該goroutine在2s後,關閉channel。此時,主協程會在select中的case <-done分支中得到通知,跳出死迴圈。而在此之前,會執行default分支的**,這裡是什麼都不做。

select{}
以上的語句會永遠等待,直到有訊號中斷。

本文總結了select+channel模式的特點和各種用法,可以針對具體情況選擇使用相應的模式。

Go 併發程式設計

go語言宣揚用通訊的方式共享資料。go語言以獨特的併發程式設計模型傲視群雄,與併發程式設計關係最緊密的 包就是sync包,意思是同步。同步的用途有兩個,乙個是避免多個執行緒在同一時刻操作同乙個資料塊,另乙個是協調多個執行緒,以避免它們在同一時刻執行同一塊 由於這一的資料庫和 塊的背後都隱含著一種或多...

go併發程式設計

x ch 從ch中接收值並賦值給變數x ch 從ch中接收值,忽略結果關閉 我們通過呼叫內建的close函式來關閉通道。close ch 關於關閉通道需要注意的事情是,只有在通知接收方goroutine所有的資料都傳送完畢的時候才需要關閉通道。通道是可以被垃圾 機制 的,它和關閉檔案是不一樣的,在結...

Go併發程式設計實踐

併發程式設計一直是golang區別與其他語言的很大優勢,也是實際工作場景中經常遇到的。近日筆者在組內分享了我們常見的併發場景,及 示例,以期望大家能在遇到相同場景下,能快速的想到解決方案,或者是拿這些方案與自己實現的比較,取長補短。現整理出來與大家共享。回到頂部 很多時候,我們只想併發的做一件事情,...