Go語言中使用了CSP模型來進行線程通信,準確地說,是輕量級線程goroutine之間的通信。 CSP模型和Actor模型類似,也是由獨立的,並發執行的實體所構成,實體之間也是透過發送訊息進行通訊的。
一.Actor模型與CSP模型區別:
Actor之間直接通訊,而CSP是透過Channel通訊,在耦合度上兩者是有差別的,後者更加鬆散耦合。
主要的差異在於:CSP模型中訊息的發送者和接收者之間透過Channel鬆耦合,發送者不知道自己訊息被哪個接收者消費了,接收者也不知道是哪個發送者發送的訊息。在Actor模型中,由於Actor可以根據自己的狀態選擇處理哪個傳入訊息,因此自主性可控性會比較好。
在Go語言中為了不阻塞進程,程式設計師必須檢查不同的傳入訊息,以便預見確保正確的順序。 CSP好處是Channel不需要緩衝訊息,而Actor理論上需要一個無限大小的郵箱作為訊息緩衝。
CSP模型的訊息發送方只能在接收方準備好接收訊息時才能發送訊息。相反,Actor模型中的消息傳遞是異步 的,即訊息的發送和接收無需在同一時間進行,發送方可以在接收方準備好接收訊息前將訊息發送出去。
二.Go Channel詳解
Channel類型的定義格式如下:
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
它包含三種類型的定義。可選的<-代表channel的方向。如果沒有指定方向,那麼Channel就是雙向的,既可以接收數據,也可以發送數據。
chan T // 可以接收和发送类型为 T 的数据 chan<- float64 // 只可以用来发送 float64 类型的数据 <-chan int // 只可以用来接收 int 类型的数据
<-總是優先和最左邊的類型結合。 (The <- operator associates with the leftmost chan possible)
c := make(chan bool) //创建一个无缓冲的bool型Channel c <- x //向一个Channel发送一个值 <- c //从一个Channel中接收一个值 x = <- c //从Channel c接收一个值并将其存储到x中 x, ok = <- c //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false
預設情況下,channel發送方和接收方會一直阻塞直到對方準備好發送或者接收,這就使得Go語言無需加鎖或者其他條件,天然支持了並發。
使用make初始化Channel,並且可以設定容量:
make(chan int, 100) #//创建一个有缓冲的int型Channel
容量(capacity)代表Channel容納的最多的元素的數量,代表Channel的快取的大小。
如果沒有設定容量,或容量設定為0, 說明Channel沒有快取。
你可以在多個goroutine從/往 一個channel 中 receive/send 資料, 不必考慮額外的同步措施。
Channel可以作為一個先入先出(FIFO)的佇列,接收的資料和所傳送的資料的順序是一致的。
不含緩衝的Channel兼具通訊和同步兩種特性,在並發開發中頗受青睞。
// _Channels_ are the pipes that connect concurrent // goroutines. You can send values into channels from one // goroutine and receive those values into another // goroutine. package main import "fmt" func main() { // Create a new channel with `make(chan val-type)`. // Channels are typed by the values they convey. messages := make(chan string) // _Send_ a value into a channel using the `channel <-` // syntax. Here we send `"ping"` to the `messages` // channel we made above, from a new goroutine. go func() { messages <- "ping" }() // The `<-channel` syntax _receives_ a value from the // channel. Here we'll receive the `"ping"` message // we sent above and print it out. msg := <-messages fmt.Println(msg) }
這裡我們創建了一個沒有緩衝的string類型Channel,然後在一個goroutine把「ping」用channel<-傳給了這個Channel。 <-channel收到了這個值,然後在main函數列印出來。其實這裡我們利用Channel悄悄把「ping」message從一個goroutine轉移到了main goroutine,實現了線程間(準確的說,goroutine之間的)通訊。
因為channel發送方和接收方會一直阻塞直到對方準備好發送或接收,這就使得我們在程式末尾等」ping」 message而無需其他的同步操作。
再看一個範例:使用者自訂的goroutine完成某個操作之後提醒main goroutine:
// We can use channels to synchronize execution// across goroutines. Here's an example of using a// blocking receive to wait for a goroutine to finish.package mainimport "fmt"import "time"// This is the function we'll run in a goroutine. The// `done` channel will be used to notify another// goroutine that this function's work is done.func worker(done chan bool) { fmt.Print("working...") time.Sleep(time.Second) fmt.Println("done") // Send a value to notify that we're done. done <- true}func main() { // Start a worker goroutine, giving it the channel to // notify on. done := make(chan bool, 1) go worker(done) // Block until we receive a notification from the // worker on the channel. <-done }
################################################################################################ ###Go語言中使用了CSP模型來進行線程通信,準確地說,是輕量級線程goroutine之間的通信。 CSP模型和Actor模型類似,也是由獨立的,並發執行的實體所構成,實體之間也是透過發送訊息進行通訊的。 ######【推薦課程:###Go影片教學###】#######
以上是Go語言裡Channel相關解釋的詳細內容。更多資訊請關注PHP中文網其他相關文章!