go語言channel生產者、消費者模式實踐

乾飯人小羽 發佈 2023-12-19T03:21:11.596856+00:00

面已經講過很多Golang系列知識,包括並發,鎖等內容,感興趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863.html,接下來講幾個golang常見的並發模型,今天先說說生產者消費者模型。

面已經講過很多Golang系列知識,包括並發,鎖等內容,感興趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863.html,

接下來講幾個golang常見的並發模型,今天先說說生產者消費者模型。

生產者消費者模型



生產者:發送數據端

消費者:接收數據端

緩衝區:
  1. 解耦(降低生產者和消費者之間耦合度)

  2. 並發(生產者消費者數量不對等時,能保持正常通信)

  3. 緩存(生產者和消費者 數據處理速度不一致時,暫存數據)

如何實現?

生產者消費者模型是非常常見的並發模型,而且golang提供了chan類型,可以很方便的實現。

根據 golang的官方文檔,使用chan就可以實現生產者和消費者之間的數據和狀態同步。

  • 通過chan在生產者和消費者之間傳遞數據(ch)和同步狀態(done);
  • chan作為參數傳遞時是引用傳遞,不需要使用指針;
  • chan是協程安全的,多個goroutine之間不需要鎖;
  • chan的close事件可以被recv獲取,close事件一定在正常數據讀完之後,機制類似於read到EOF;

示例代碼:

package main

import "fmt"

func Producer(ch chan int) {
  for i := 1; i <= 10; i++ {
    ch <- i
  }
  close(ch)
}

func consumer(id int, ch chan int, done chan bool) {
  for {
    value, ok := <-ch
    if ok {
      fmt.Printf("id: %d, recv: %d\n", id, value)
    } else {
      fmt.Printf("id: %d, closed\n", id)
      break
    }
  }
  done <- true
}

func main() {
  ch := make(chan int, 3)

  coNum := 2


  for i := 1; i <= coNum; i++ {
    go Consumer(i, ch, done)
  }

  go Producer(ch)

  for i := 1; i <= coNum; i++ {
    <-done
  }
}


運行結果:
id: 2, recv: 1
id: 1, recv: 2
id: 1, recv: 4
id: 1, recv: 5
id: 1, recv: 6
id: 2, recv: 3
id: 2, recv: 8
id: 2, recv: 9
id: 2, recv: 10
id: 2, closed
id: 1, recv: 7
id: 1, closed

簡單說明:

1、首先創建一個雙向的channel,

2.、然後開啟一個新的goroutine,把雙向通道作為參數傳遞到producer方法中,同時轉成只寫通道。子協程開始執行循環,向只寫通道中添加數據,這就是生產者。

3、主協程,直接調用consumer方法,該方法將雙向通道轉成只讀通道,通過循環每次從通道中讀取數據,這就是消費者。


注意:channel作為參數傳遞,是引用傳遞。

緩衝區的好處

1:解耦
假設生產者和消費者分別是兩個類。如果讓生產者直接調用消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。將來如果消費者的代碼發生變化,可能會直接影響到生產者。而如果兩者都依賴於某個緩衝區,兩者之間不直接依賴,耦合度也就相應降低了。

2:處理並發
生產者直接調用消費者的某個方法,還有另一個弊端。由於函數調用是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只好一直等在那邊。萬一消費者處理數據很慢,生產者只能無端浪費時間。
使用了生產者/消費者模式之後,生產者和消費者可以是兩個獨立的並發主體。生產者把製造出來的數據往緩衝區一丟,就可以再去生產下一個數據。基本上不用依賴消費者的處理速度。
其實最當初這個生產者消費者模式,主要就是用來處理並發問題的。

3:緩存
如果生產者製造數據的速度時快時慢,緩衝區的好處就體現出來了。當數據製造快的時候,消費者來不及處理,未處理的數據可以暫時存在緩衝區中。等生產者的製造速度慢下來,消費者再慢慢處理掉。

最後

以上,就把golang生產者消費者模型簡單介紹完了,希望能對大家有所幫助。

關鍵字: