Newbie to Go unsure of how to make Channel code less "sequential"

205 views
Skip to first unread message

mark...@gmail.com

unread,
Oct 10, 2014, 11:31:43 AM10/10/14
to golan...@googlegroups.com
Hi,

The issue I'm having is the channel based code I'm running is sequential, even though my understanding was that it should be more asynchronous. I'm probably just mistaken in how channels work.

I'm running through existing code from Rob Pike's "Go Concurrency Patterns" slides. The following is an example:



import
(
"fmt"
"math/rand"
"time"
)
 
func fanIn(input1, input2 <-chan string) <-chan string {
c := make(chan string)
 
go func(){ for { c <- <-input1 } }()
go func(){ for { c <- <-input2 } }()
 
return c
}
 
func main() {
c := fanIn(boring("foo"), boring("bar"))
 
for i := 0; i < 10; i++ {
fmt.Printf("%s\n", <-c)
}
 
fmt.Println("Finished")
}
 
func boring(msg string) <-chan string {
c := make(chan string)
 
go func() {
for i := 0; ; i++ {
c <- fmt.Sprintf("%s %d", msg, i)
t := time.Duration(rand.Intn(1e3)) * time.Millisecond
time.Sleep(t)
}
}()
 
return c
}

The output of this code is:

foo 0
bar 0
foo 1
bar 1
foo 2
bar 2
foo 3
bar 3
foo 4
bar 4
Finished

But how do I make the output less sequential? Or is that even needed. The channels do appear to be context switching as per how concurrency works. Maybe I'm just concerned how performant this type of concurrency is in relation to how threads typically work.

Tamás Gulácsi

unread,
Oct 10, 2014, 2:48:57 PM10/10/14
to golan...@googlegroups.com
The playground does not have real randomness and real time, but Go is deterministic.
If you don't use more CPU threads (GOMAXPROCS=1 by default), then you have to give more room to your goroutines, as your code is a classical "lockstep".

If you use buffered channels, it is closer to what you want: http://play.golang.org/p/uW1lw2TIww

andrey mirtchovski

unread,
Oct 10, 2014, 2:54:11 PM10/10/14
to mark...@gmail.com, golang-nuts
you're using random numbers between 0 and 999 but in the majority of
cases they will be pretty close to each other (only rarely will you
get one sleeping for 1 millisecond and the other sleeping for 999
milliseconds), and because you're not seeding the random number
generator you always get the same sequence for foo and bar: 81 and
887. if you want more randomness put in a larger factor in the time
difference, for example:

t := time.Duration(rand.Intn(3)*rand.Intn(1e3)) * time.Millisecond

and if you want to have a different variation each run you call
rand.Srand(time.Now().UnixNano()) in main (note that this is not a
proper way to seed a random number generator for serious
applications). here's an example:

$ for i in 1 2 3; do ./t; done
foo
foo
foo
foo
foo
foo
bar
foo
bar
foo
Finished
foo
foo
foo
bar
bar
foo
foo
foo
bar
foo
Finished
foo
bar
bar
foo
foo
foo
foo
bar
bar
foo
Finished
Message has been deleted

Blake Caldwell

unread,
Oct 11, 2014, 12:04:01 AM10/11/14
to golan...@googlegroups.com, mark...@gmail.com
As a side point, always make sure you're not leaking goroutines. Obviously, it doesn't matter in this example, where the program exits.

I updated Tamás's code to show how to do this:

(edited from my original post, since I forgot a defer :))

http://play.golang.org/p/136-A3piOW
Message has been deleted

chris dollin

unread,
Oct 11, 2014, 8:39:54 AM10/11/14
to mark...@gmail.com, golang-nuts
On 11 October 2014 13:10, <mark...@gmail.com> wrote:
> Thanks for the feedback everyone. I'm trying the seed solution suggested but
> I'm getting a strange error.
>
> The code I'm trying...
>
> t := time.Duration(rand.Seed(time.Now().UnixNano())) *
> time.Millisecond
>
> but when I run the file I get the following error:
>
> ./7.go:51: rand.Seed(time.Now().UnixNano()) used as value
>
> Not sure if I've applied it incorrectly?

rand.Seed returns no results, but you've used it somewhere that
requires one.

Chris

--
Chris "allusive" Dollin

mark...@gmail.com

unread,
Oct 11, 2014, 8:45:33 AM10/11/14
to golan...@googlegroups.com, mark...@gmail.com
Thanks for clarifying Chris. I discovered that just after I posted and so I deleted my earlier post.

M.
Reply all
Reply to author
Forward
0 new messages