I'm probably missing something, or not understanding something in how Go handles concurrency (or in my knowledge of concurrency itself), i've devised a little bit of code to understand a multiple producer/consumer.
This is the code:
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()
}
When run it prints (mostly in order) all the numbers from 1 to 1000 (200 consumers getting a number 5 times each). I would've expected that some consumer would print the exact same number but it seems that the requestChan is working like a barrier preventing this even if there are 20 goroutines serving the generateStuff that generate the number by increasing a global variable.
What am i getting wrong about Go or Concurrency in general?
I would've expected a situation in like two go routines of type generateStuff would've been woke up together and increase seq at the same time thus having something like two consumers printing the same number two times.
EDIT Code on playgolang: http://play.golang.org/p/eRzNXjdxtZ