blog

12020-10-01

SEAN K.H. LIAO

Synchronization

From GopherCon 2018: Bryan C. Mills - Rethinking Classical Concurrency Patterns

exclusive access

func ExampleChannelLock() {
        mu := make(chan int, 1)
        mu <- 0

        x := <- mu
        x = x * 2
        mu <- x
}()

broadcast

Alternatively start with nil inner channel for nonblocking start (and check for nils).

func ExampleBroadcast() {
        bc := make(chan chan struct{}, 1)
        bc <- make(chan struct{})

        // wait
        go func() {
                s := <-bc
                bc <- s
                select {
                case <-s:
                }
        }()

        // signal
        s := <-bc
        close(s)
        bc <- make(chan struct)
}

limited concurrency

less useful when you may need to recursively add work

func ExampleSemaphore() {
        sem := make(chan struct{}, limit)
        for _, task := range tasks {
                sem <- struct{}
                go func() {
                        work(task)
                        <-sem
                }()
        }

        // wait
        for n := limit; n > 0; n-- {
                sem <- struct{}
        }
}