我可能错过了某些东西,或不理解Go如何处理并发(或者我的并发知识),我已经设计了一些代码来理解多个生产者/消费者。并发与多个生产者/多个消费者
这是代码:
package main
import (
"fmt"
"time"
// "math/rand"
"sync"
)
var seq uint64 = 0
var generatorChan chan uint64
var requestChan chan uint64
func makeTimestamp() int64 {
return time.Now().UnixNano()/int64(time.Millisecond)
}
func generateStuff(genId int) {
var crap uint64
for {
crap = <-requestChan
// <- requestChan
seq = seq+1
fmt.Println("Gen ", genId, " - From : ", crap, " @", makeTimestamp())
generatorChan <- uint64(seq)
}
}
func concurrentPrint(id int, work *sync.WaitGroup) {
defer work.Done()
for i := 0; i < 5; i++ {
requestChan<-uint64(id)
fmt.Println("Conc", id, ": ", <-generatorChan)
}
}
func main() {
generatorChan = make(chan uint64)
requestChan = make(chan uint64)
var wg sync.WaitGroup
for i := 0; i < 20; i++ {
go generateStuff(i)
}
maximumWorker := 200
wg.Add(maximumWorker)
for i := 0; i < maximumWorker; i++ {
go concurrentPrint(i, &wg)
}
wg.Wait()
}
当从1运行它打印(主要是按顺序)的所有数字至1000(200名消费者得到一个数每5次)。 我本来预计一些消费者会打印完全相同的号码,但看起来请求代码正在阻止这种情况,即使有20个goroutines服务于generateStuff,它们通过增加一个全局变量。
我在Go或Concurrency中遇到了什么问题?
我本来预料到类似于类似的两个去程序的情况,generateStuff会一起醒来,同时增加seq,因此有两个消费者打印相同数字两次。
EDIT代码上playgolang:http://play.golang.org/p/eRzNXjdxtZ
注意,你有获得潜在的数据赛跑到全局'seq'变量(除了未缓冲的'requestChan'可能会使它们分开)。 – 2015-04-04 20:25:20
是的,这是我所期望的戴夫,一些非确定性的行为给我不是所有的数字从1到1000,但有些不同。 在这个例子中,chans被缓冲了http://play.golang.org/p/tq7-6Bc0hL,仍然得到相同的结果。 – Marlon 2015-04-04 20:33:19
你用'GOMAXPROCS'> 1运行了吗? (也许使用'-race') – 2015-04-04 20:34:27