golang 並發編程之生產者消費者
golang 最吸引人的地方可能就是並發了,無論代碼的編寫上,還是性能上面,golang 都有絕對的優勢
學習一個語言的並發特性,我喜歡實現一個生產者消費者模型,這個模型非常經典,適用於很多的並發場景,下面我通過這個模型,來簡單介紹一下 golang 的並發編程
go 並發語法
協程 go
協程是 golang 並發的最小單元,類似於其他語言的線程,只不過線程的實現借助了操作系統的實現,每次線程的調度都是一次系統調用,需要從用戶態切換到內核態,這是一項非常耗時的操作,因此一般的程序裏面線程太多會導致大量的性能耗費在線程切換上。而在 golang 內部實現了這種調度,協程在這種調度下面的切換非常的輕量級,成百上千的協程跑在一個 golang 程序裏面是很正常的事情
golang 為並發而生,啟動一個協程的語法非常簡單,使用 go
關鍵字即可
go func () {
// do something
}
同步信號 sync.WaitGroup
多個協程之間可以通過 sync.WaitGroup
同步,這個類似於 Linux 裏面的信號量
var wg sync.WaitGroup // 申明一個信號量
wg.Add(1) // 信號量加一
wg.Done() // 信號量減一
wg.Wait() // 信號量為正時阻塞,直到信號量為0時被喚醒
通道 chan
通道可以理解為一個消息隊列,生產者往隊列裏面放,消費者從隊列裏面取。通道可以使用 close
關閉
ic := make(chan int, 10) // 申明一個通道
ic <- 10 // 往通道裏面放
i := <- ic // 從通道裏面取
close(ic) // 關閉通道
生產者消費者實現
定義產品類
這個產品類根據具體的業務需求定義
type Product struct {
name int
value int
}
生產者
如果 stop
標誌不為 false
,不斷地往通道裏面放 product
,完成之後信號量完成
func producer(wg *sync.WaitGroup, products chan<- Product, name int , stop *bool) {
for !*stop {
product := Product{name: name, value: rand.Int()}
products <- product
fmt.Printf("producer %v produce a product: %#v\n", name, product)
time.Sleep(time.Duration(200+rand.Intn(1000)) * time.Millisecond)
}
wg.Done()
}
消費者
不斷地從通道裏面取 product,然後作對應的處理,直到通道被關閉,並且 products 裏面為空, for 循環才會終止,而這正是我們期望的
func consumer(wg *sync.WaitGroup, products <-chan Product, name int) {
for product := range products {
fmt.Printf("consumer %v consume a product: %#v\n", name, product)
time.Sleep(time.Duration(200+rand.Intn(1000)) * time.Millisecond)
}
wg.Done()
}
主線程
var wgp sync.WaitGroup
var wgc sync.WaitGroup
stop := false
products := make(chan Product, 10)
// 創建 5 個生產者和 5 個消費者
for i := 0; i < 5; i++ {
go producer(&wgp, products, i, &stop)
go consumer(&wgc, products, i)
wgp.Add(1)
wgc.Add(1)
}
time.Sleep(time.Duration(1) * time.Second)
stop = true // 設置生產者終止信號
wgp.Wait() // 等待生產者退出
close(products) // 關閉通道
wgc.Wait() // 等待消費者退出
轉載請註明出處
本文鏈接:http://hatlonely.github.io/2018/03/11/golang-%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85/
golang 並發編程之生產者消費者