golang channel的使用以及調度原理

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寫數據。
相關文章
相關標籤/搜索