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
  done := make(chan bool, coNum)
  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生產者消費者模型簡單介紹完了,希望能對大家有所幫助。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM