這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go concurrency model :原文地址:
http://www.oschina.net/translate/go-concurrency-patterns-pipelines?print
特性:原子並發特性
優勢:Golang可有效使用I/O和多CPU特性。
1 什麼是管道
在Golang對於管道沒有明確的定義;它只是許多種並發程式中的一種。管道是通道串連的一系列階段, 每個階段是一組goroutine運行相同的功能。在每個階段,goroutine運行步驟為:
從上遊經過入境通道接受值
對資料執行一些功能操作,通常會產生新的值
從下遊經過出境通道發送值
除了開始和最後階段只有一個入境通道或者一個出境通道外,其他每個階段有任意數量的入境通道和出境通道,。開始階段有時又稱為源或者生產者;最後一個階段又稱為sink或者消費者。
舉個例子:
第一階段:gen,以從列表讀出整數的方式轉換整數列表到一個通道。gen函數開始goroutine後, 在通道上發送整數並且在在所有的值被發送完後將通道關閉:
func gen(nums ...int) <-chan int { out := make(chan int) go func() { for _, n := range nums { out <- n } close(out) }() return out}
第二階段:sq,從通道接受整數,然後將接受到的每個整數值的平方後返回到一個通道 。在入境通道關閉和發送所有下行值的階段結束後,關閉出口通道:
func sq(in <-chan int) <-chan int { out := make(chan int) go func() { for n := range in { out <- n * n } close(out)08 }() return out}main函數建立了通道並運行最後一個階段:它接受來自第二階段的值並列印出每個值,直到通道關閉:
func main() { // Set up the pipeline. c := gen(2, 3) out := sq(c) // Consume the output. fmt.Println(<-out) // 4 fmt.Println(<-out) // 9
扇出,扇入
扇出(fan-out):多個函數能從相同的通道中讀資料,直到通道關閉;這提供了一種在一組“人員”中分發任務的方式,使得CPU和I/O的平行處理.
扇入(fan-in):一個函數能從多個輸入中讀取並處理資料,而這多個輸入通道映射到一個單通道,該單通道隨著所有輸入的結束而關閉。
短暫停止
管道函數模型:
這個模型允許每一個接收階段通過range迴圈的寫資料,確保一旦所有向下遊發送的值發送成功,所有的goroutine退出。
但在一個真實的管道上,階段並不總是接收所有的入境值。有時設計是這樣的:接收者可能只需要一個子集值就能取得進展。更多時候是一個階段早早的退出,因為一個入境值代表一個早期階段的錯誤。 在這兩種情況下接收者不應該等待剩餘的值到達,我們想要早期階段停止產生後續階段不需要的值。
顯式取消
當main沒有接受完out所有的值就決定退出時,它必須告知上遊狀態(upstream stage)的goroutines,讓它丟棄正在發送中的資料。通過在一個叫做done的channel上發送資料,即可實現。例子裡有兩個受阻的發送方,所以發送的值有兩組:
下面列出了構建管道的指南:
管道要麼保證足夠能存下所有發送資料的緩衝區,要麼接收來自接收者明確的要放棄 channel 的訊號,來保證釋放寄件者。