Golang協程與通道整理

2022-03-05 18:45:31 字數 1988 閱讀 6500

協程goroutine

不由os排程,而是使用者層自行釋放cpu,從而在執行體之間切換。go在底層進行協助實現

涉及系統呼叫的地方由go標準庫協助釋放cpu

總之,不通過os進行切換,自行切換,系統執行開支大大降低

通道channel

併發程式設計的關鍵在於執行體之間的通訊,go通過通過channel進行通訊

channel可以認為類似其他os體系中的訊息佇列,只不過在go中原生支援,因而易用

訊息佇列有哪些值得關注的地方?常見問題包括建立、關閉或刪除、阻塞、超時、優先順序等,golang中也不例外。羅列如下:

可否探測佇列是滿或空?或者說是否可以不阻塞地嘗試讀寫?

讀阻塞和寫阻塞時關閉會怎樣?

關閉後未讀取的訊息會被拋棄?

往關閉的channel傳送資料或讀取資料會怎樣?

怎樣探測channel的關閉?

兩個地方讀或寫阻塞同乙個channel,有沒有優先順序?

是否可以設定阻塞的超時時間?

阻塞時怎樣可以被彈出來?比如某些訊號?

事實上,知道存在這些問題並進行分門別類是重要的,但知道這些問題的答案卻不緊要,因為一般不會太過古怪,使用時臨時試驗一下即可。

已知的部分答案:

好像不能不阻塞地嘗試讀寫

關閉會導致退出阻塞(似乎是乙個不錯的特性)

可以探測關閉

channel本身不能設定超時

了解這些似乎已經足夠。

與眾不同的地方值得我們重點留意,包括:

除基本讀寫方式外,還有哪些特別的讀寫方式?在阻塞、關閉、超時方面又有什麼不同?發現了select、range兩個關鍵字

推薦的多通道讀

推薦的同步方法

推薦的超時方法

select

select可以實現無阻塞的多通道嘗試讀寫,以及阻塞超時

varc, c1, c2, c3chanint

vari1, i2 int

selectelse

default: // 如果case都阻塞,則走default,如果無default,則阻塞在case

// default中可以不讀寫任何通道,那麼只要default提供不阻塞的出路,就相當於實現了對case的無阻塞嘗試讀寫

print( "no communication\n")

}實現阻塞超時的方法是,只要不給default出路,而在case中實現乙個超時

timeout :=make(chanbool, 1)

gofunc() ()

// 用timeout這個通道作為阻塞超時的出路

select

range

range可以在for迴圈中讀取channel

go文件的翻譯文是:對於通道,其迭代值產生為在該通道上傳送的連續值,直到該通道被關閉。若該通道為 nil,則range表示式將永遠阻塞

經過試驗,range會阻塞,並且可以通過關閉channel來解除阻塞。

packagemain

import(

"fmt"

)funcmain()

}()forw :=rangech

}fmt.println( "after range or close ch!" )

}golang的併發程式設計還有其他細節,但以上是最主要脈絡。

Golang協程與通道整理

協程goroutine 不由os排程,而是使用者層自行釋放cpu,從而在執行體之間切換。go在底層進行協助實現 涉及系統呼叫的地方由go標準庫協助釋放cpu 總之,不通過os進行切換,自行切換,系統執行開支大大降低 通道channel 併發程式設計的關鍵在於執行體之間的通訊,go通過通過channe...

golang 協程通道,map,redis的併發性

假如我們沒有用協程通道或者加鎖的方式,直接併發使用map,會出現線性不安全 例如 package main import time fmt var tmap map int int func main time.sleep 1e10 fmt.println map len tmap func put...

Go 協程 通道

目錄 go 協程 go 通道 go 協程go 協程可以看作是輕量級執行緒。與執行緒相比,建立乙個go協程的成本很小。因此在go應用中,常常會看到有數以千計的go協程併發地執行 go 協程相比於執行緒的優勢 啟動乙個go協程 在呼叫函式和方法時,在前面加上關鍵字go,可以讓乙個新的go協程併發執行 p...