新的一年開始了,不管今天以前發生了什麼,向前看,就夠了。 說到channel,就一定要說一說線程了。任何實際項目,無論大小,併發是必然存在的。併發的存在,就涉及到線程通信。在當下的開發語言中,線程通訊主要有兩種,共用記憶體與消息傳遞。共用記憶體一定都很熟悉,通過共同操作同一對象,實現線程間通訊。消息傳遞
新的一年開始了,不管今天以前發生了什麼,向前看,就夠了。
說到channel,就一定要說一說線程了。任何實際項目,無論大小,併發是必然存在的。併發的存在,就涉及到線程通信。在當下的開發語言中,線程通訊主要有兩種,共用記憶體與消息傳遞。共用記憶體一定都很熟悉,通過共同操作同一對象,實現線程間通訊。消息傳遞即通過類似聊天的方式。golang對併發的處理採用了協程的技術。golang的goroutine就是協程的實現。協程的概念很早就有,簡單的理解為輕量級線程,goroutine就是為瞭解決併發任務間的通信而設計的。golang解決通信的理念是:不要通過共用記憶體來通信,而應該通過通信來共用記憶體。golang解決方案是消息傳遞機制,消息的傳遞就是通過channel來實現的。
channel的使用很簡單,這裡就不在粘別人的東西了。現在談一談對channe阻塞l的理解。
發送者角度:對於同一個通道,發送操作(協程或者函數中的),在接收者準備好之前是阻塞的。如果chan中的數據無人接收,就無法再給通道傳入其他數據。因為新的輸入無法在通道非空的情況下傳入。所以發送操作會等待 chan 再次變為可用狀態:就是通道值被接收時(可以傳入變數)。
接收者角度:對於同一個通道,接收操作是阻塞的(協程或函數中的),直到發送者可用:如果通道中沒有數據,接收者就阻塞了。
通過一個簡單的例子來說明:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func f1(in chan int) { 8 fmt.Println(<-in) 9 } 10 11 func main() { 12 out := make(chan int) 13 out <- 2 14 go f1(out) 15 }
運行結果:fatal error: all goroutines are asleep - deadlock!
這是由於第13行之前不存在對out的接收,所以,對於out <- 2來說,永遠是阻塞的,即一直會等下去。
將13,14行互換
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func f1(in chan int) { 8 fmt.Println(<-in) 9 } 10 11 func main() { 12 out := make(chan int) 13 go f1(out) 14 out <- 2 15 }
運行結果:2
14行前存在對管道的讀操作,所以out <- 2 是合法的。就像前文說的,發送操作在接收者準備好之前是阻塞的。