What is. synchronizing this code?

I have ran it, and it is alway the same order (three, one, two). Why is this, should it not be nondeterministic ?

package main

import (
    "fmt"
    "sync"
)

type Button struct {
    Clicked *sync.Cond
}

func subscribe(c *sync.Cond, fn func()) {
    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        wg.Done()

        c.L.Lock()
        defer c.L.Unlock()

        c.Wait()
        fn()
    }()

    wg.Wait()
}

func main() {
    button := Button{Clicked: sync.NewCond(&sync.Mutex{})}

    var wg sync.WaitGroup
    wg.Add(3)

    subscribe(button.Clicked, func() {
        fmt.Println("One")

        wg.Done()
    })

    subscribe(button.Clicked, func() {
        fmt.Println("Two")

        wg.Done()
    })

    subscribe(button.Clicked, func() {
        fmt.Println("Three")

        wg.Done()
    })

    button.Clicked.Broadcast()
    wg.Wait()
}

what do you think ?

I think that 3 go routines are probably added to the sync.Cond wait list in order each time, so when you run button.Clicked.Broadcast() they always run in the same order.

Broadcast doesn’t specify anything about ordering, so I expect it just runs down the slice waking each one in turn.

func (c *Cond) Broadcast()
Broadcast wakes all goroutines waiting on c.

It is allowed but not required for the caller to hold c.L during the call.

in a similar manner, how come this code always prints the same results: https://play.golang.org/p/mbCIa-F7Vmz

How can this be, what is synchronizing the two goroutines ?

Don’t forget the playground caches the output of stuff…

If I compile and run this locally I don’t get the same answer each time

$ go build z.go
$ ./z
def
abc
$ ./z
def
abc
$ ./z
abc
def
$ ./z
def
abc
$ ./z
abc
def

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.