Skip to content

Instantly share code, notes, and snippets.

@bradclawsie
Last active January 26, 2017 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradclawsie/a344b471d6f3d023aa9f200516407cbd to your computer and use it in GitHub Desktop.
Save bradclawsie/a344b471d6f3d023aa9f200516407cbd to your computer and use it in GitHub Desktop.
curious correct Go program
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan struct{},1)
go func() {
time.Sleep(100 * time.Millisecond)
fmt.Printf("0 ")
c <- struct{}{}
fmt.Printf("1 ")
c <- struct{}{}
fmt.Printf("2 ")
c <- struct{}{}
fmt.Printf("3 ")
return
}()
<- c
fmt.Printf("done ")
}
@bradclawsie
Copy link
Author

bradclawsie commented Jan 26, 2017

This program runs and exist properly although our intuition might say it will fail.

The program doesn't deadlock and it prints "done" even though it appears to be wrong at first glance.

The chan is of length 1, how is it we can put more than one struct{}{} into it? We can't and we don't. The goroutine is launched while the outer scope blocks on polling the chan. The goroutine enqueues a struct{}{}, and the outer scope dequeues it. While that is happening, the goroutine now can (and typically does) enqueue another struct{}{} before the final "done" message is printed. At this point, our goroutine should be "stuck" waiting to enqueue a new struct{}{}, but it doesn't matter, the program exits and the goroutine itself is stopped.

This shows the need for proper synchronization without cleverness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment