golang協程——通道channel阻塞

  新的一年開始了,無論今天之前發生了什麼,向前看,就夠了。golang

  說到channel,就必定要說一說線程了。任何實際項目,不管大小,併發是必然存在的。併發的存在,就涉及到線程通訊。在當下的開發語言中,線程通信主要有兩種,共享內存與消息傳遞。共享內存必定都很熟悉,經過共同操做同一對象,實現線程間通信。消息傳遞即經過相似聊天的方式。golang對併發的處理採用了協程的技術。golang的goroutine就是協程的實現。協程的概念很早就有,簡單的理解爲輕量級線程,goroutine就是爲了解決併發任務間的通訊而設計的。golang解決通訊的理念是:不要經過共享內存來通訊,而應該經過通訊來共享內存。golang解決方案是消息傳遞機制,消息的傳遞就是經過channel來實現的。併發

  channel的使用很簡單,這裏就不在粘別人的東西了。如今談一談對channe阻塞l的理解。  函數

  發送者角度:對於同一個通道,發送操做(協程或者函數中的),在接收者準備好以前是阻塞的。若是chan中的數據無人接收,就沒法再給通道傳入其餘數據。由於新的輸入沒法在通道非空的狀況下傳入。因此發送操做會等待 chan 再次變爲可用狀態:就是通道值被接收時(能夠傳入變量)。spa

  接收者角度:對於同一個通道,接收操做是阻塞的(協程或函數中的),直到發送者可用:若是通道中沒有數據,接收者就阻塞了。線程

  經過一個簡單的例子來講明:設計

  

 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!code

  這是因爲第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 }

  運行結果:2blog

  14行前存在對管道的讀操做,因此out <- 2 是合法的。就像前文說的,發送操做在接收者準備好以前是阻塞的。

相關文章
相關標籤/搜索