我正在嘗試使用緩沖通道在 Golang 中創建生產者-消費者訊息佇列系統。這是我的實作。
package main
import "fmt"
type MessageQueue struct {
storage chan int
count int
}
var done = make(chan bool)
func NewMessageQueue(count int) *MessageQueue {
ret := &MessageQueue{
count: count,
storage: make(chan int, count),
}
return ret
}
func (m *MessageQueue) Produce() {
for i := 0; i < m.count; i {
m.storage <- i 1
}
done <- true
}
func (m *MessageQueue) Consume(f func(int) int) {
for each := range m.storage {
fmt.Printf("%d ", f(each))
}
}
func main() {
op1 := func(a int) int {
return a * a
}
msq := NewMessageQueue(10)
go msq.Produce()
go msq.Consume(op1)
<-done
}
但不幸的是,當我運行時我無法獲得輸出go run main.go但是檢查是否有任何競爭條件,當我嘗試時go run -race main.go,我確實得到了輸出。我無法理解為什么會這樣。有人能幫我一下嗎?
uj5u.com熱心網友回復:
當您的生產者可以發送值時,它會在done通道上發送一個值,以便您的應用程式可以立即終止。
相反,當生產者完成時,它應該關閉m.storage通道,表示不再發送值,并且不要在 上發送值done,因為你還沒有完成!
當值被消耗時你就完成了,所以在donein上發送一個值Consume():
func (m *MessageQueue) Produce() {
for i := 0; i < m.count; i {
m.storage <- i 1
}
close(m.storage)
}
func (m *MessageQueue) Consume(f func(int) int) {
for each := range m.storage {
fmt.Printf("%d ", f(each))
}
done <- true
}
這將輸出(在Go Playground上嘗試):
1 4 9 16 25 36 49 64 81 100
通道是必需的done,因為消耗不會發生在maingoroutine 中,maingoroutine 必須等待它結束。
如果你在maingoroutine 上進行消費,你可以洗掉done通道:
msq := NewMessageQueue(10)
go msq.Produce()
msq.Consume(op1)
在Go Playground上試試這個。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/447714.html
下一篇:出現錯誤“dialtcpxxx:xxx:xxx:xxx:3306:connect:connectiondenied”的情況是什么以及如何避免此錯誤
