golang channel的使用以及調度原理golang
爲了併發的goroutines之間的通信,golang使用了管道channel。 能夠經過一個goroutines向channel發送數據,而後從另外一個goroutine接收它。 一般咱們會使用make來建立channel ----- make(chan valType, [size])。 寫入 c <- data 讀取 data := <-c Golang的channel分爲緩衝和非緩衝的兩種。主要區別:緩衝chanel是同步的,非緩衝channel是非同步的。 舉個例子: c1 := make(chan int) // 無緩衝: c1 <- 1,當前協程阻塞。 c2 := make(chan int, 1) // 有緩衝: c2 <- 1,當前協程不會阻塞,c2 <- 2,此時1沒有被取走,當前協程才阻塞。 備註: 一、給一個nil channel發送數據,形成永遠阻塞。 二、從一個nil channel接收數據,形成永遠阻塞。 三、給一個已經關閉的channel發送數據,引發panic。 四、從一個已經關閉的channel接收數據,當即返回一個零值(false : bool, 0 : int, 0.0 : float, "" : string, nil : pointer, function, interface, slice, channel, map)。 五、channel關閉屢次會引發panic,channel不能close大於1次。 六、能夠用兩個返回值(valeu, b := <-c)來捕獲channel是否關閉,b取值false或true。 緩衝channel的調度: 1、寫數據: 一、協程1往channel寫數據,buffer爲空,讀隊列爲空,直接寫入buffer並返回。 二、協程1往channel寫數據,buffer爲空,讀隊列非空(協程2阻塞在讀隊列),協程1將數據交給協程2並喚醒協程2等待調度,協程1返回,調度協程2取得數據並返回。 三、協程1往channel寫數據,buffer非空未滿,直接寫入buffer並返回。 四、協程1往channel寫數據,buffer滿,加入寫隊列,阻塞當前協程1,等待有其餘協程n從channel讀數據。 2、讀數據: 一、協程2從channel讀數據,buffer非空,寫隊列非空(協程1阻塞在寫隊列),喚醒協程1等待調度,協程2從buffer讀取數據並返回,調度協程1將數據寫入buffer並返回。 二、協程2從channel讀數據,buffer非空,寫隊列空,從buffer讀取數據並返回。 三、重複步驟2直至buffer空。 3.一、若寫隊列爲空,加入讀隊列,阻塞當前協程2,等待有其餘協程n往channel寫數據。 3.二、若寫隊列非空(協程1阻塞在寫隊列),協程2從寫隊列取出數據並喚醒協程1等待調度,協程2攜帶數據返回,調度協程1返回。 非緩衝channel的調度: 1、寫數據: 一、協程1往channel寫數據,讀隊列爲空,加入寫隊列,阻塞當前協程1,等待有其餘協程n從channel讀數據。 二、協程1往channel寫數據,讀隊列非空(協程2阻塞在讀隊列),協程1將數據交給協程2並喚醒協程2等待調度,協程1返回,調度協程2取得數據並返回。 2、讀數據: 一、協程2從channel讀數據,寫隊列非空(協程1阻塞在寫隊列),協程2從寫隊列取出數據並喚醒協程1等待調度,協程2攜帶數據返回,調度協程1返回。 二、協程2從channel讀數據,寫隊列爲空,加入讀隊列,阻塞當前協程2,等待有其餘協程n往channel寫數據。