Tuesday, June 26, 2012

Waiting around for something to happen in Go

I was faced with what turned out to be a synchronization problem with a simple solution using Go.  How do you get multiple goroutines to wait for a single event to occur?  The answer is... close a channel.
package main

import (
    "fmt"
)

func main() {
    count := make(chan int)
    hold  := make(chan int)

    num := 16

    for i := 0; i < num; i++ {
        go func(i int) {
            fmt.Printf("%d ", i)
            count <- 1

            <-hold

            fmt.Printf("%d ", i)
            count <- 1
        }(i)
    }

    for reported := 0; reported != num; reported += <-count {
    }

    fmt.Printf("\n")

    close(hold)

    for reported := 0; reported != num; reported += <-count {
    }

    fmt.Printf("\n")
}
This program outputs something like:
0 2 1 4 5 3 8 9 7 6 12 13 14 11 10 15 
1 5 4 3 2 0 8 6 13 14 12 7 9 11 10 15 
The exact order will depend on the order in which the goroutines are executed.  The program uses two channels called count and hold. The count channel is used by the 16 goroutines to each inform the main program that they have performed a printing task.  The main routine counts the number of messages it has seen on the count channel so it knows when all the goroutines have completed their first print.

The main routine then closes the hold channel.  All of the goroutines are trying to receive something on that channel.  When it is closed the receive fails.

The goroutines then all print out their id number again and terminate.  The program waits for them to finish by receiving another 16 messages on the count channel.

If you enjoyed this blog post, you might enjoy my travel book for people interested in science and technology: The Geek Atlas. Signed copies of The Geek Atlas are available.

<$BlogCommentBody$>

<$BlogCommentDateTime$> <$BlogCommentDeleteIcon$>

Post a Comment

Links to this post:

<$BlogBacklinkControl$> <$BlogBacklinkTitle$> <$BlogBacklinkDeleteIcon$>
<$BlogBacklinkSnippet$>
Create a Link

<< Home