liveBook · Manning

Broadcast

As explained in Learn Concurrent Programming with Go

A broadcast pattern replicates each input message to every channel in a set of output channels.

Broadcast wakes every goroutine currently waiting on a condition variable, or replicates every input message to each output channel in a channel pipeline. Both uses let one event reach multiple concurrent receivers; they differ in whether receivers are waiting on shared state or consuming copied messages. section 5.1.3 section 9.4

With sync.Cond, Broadcast differs from Signal: Signal resumes one arbitrary waiter, while Broadcast resumes all current waiters. Use it when a shared-state change can release a group, such as when the last player joins a game or a waitgroup count reaches zero. section 5.1.3 section 6.1.4

Release players when the game is full

Each player handler locks the condition mutex, decrements playersRemaining, and waits in a loop while players remain. The handler that reduces the count to zero calls Broadcast, allowing every waiting handler to resume and begin the game. The loop rechecks shared state after waking. section 5.1.3 section 5.1.1

A condition-variable broadcast is not stored. If no goroutine is suspended in Wait when Broadcast runs, no later waiter receives it. Coordinate waiting and state updates with the associated mutex; Wait atomically releases that mutex while suspending, then reacquires it when resumed. section 5.1.2 section 5.1.1

In a channel pipeline, broadcast solves a different problem from fan-out. Fan-out load-balances distinct messages across workers; broadcast makes a copy of each message available to every downstream computation. A generic utility can create n output channels, forward each input message to all of them, and close all outputs when input ends. section 9.2.5 section 9.4

Listing 9.14 Broadcasting to multiple output channels
package listing9_14

func Broadcast[K any](quit <-chan int, input <-chan K, n int) []chan K {
    outputs := CreateAll[K](n)                           #1
    go func() {
        defer CloseAll(outputs...)                       #2
        var msg K
        moreData := true
        for moreData{
            select {
            case msg, moreData = <-input:                #3
                if moreData {                            #4
                    for _, output := range outputs {     #4
                        output <- msg                    #4
                    }
                }
            case <-quit:
                return
            }
        }
    }()
    return outputs                                       #5
}
#1 Creates n output channels of type K (see the next listing for the implementation)
#2 Once complete, closes all output channels (see the next listing for the implementation)
#3 Reads the next message from the input channel
#4 If the input channel hasn’t been closed, writes the message to each output channel
#5 Returns the set of output channels

The implementation shows the forwarding loop: receive one input value, send it to every output, stop on quit, and close all outputs on completion. Because it completes every send before reading again, one slow consumer slows the entire broadcast. section 9.2.5

Send words to two analyses

A word-processing pipeline broadcasts extracted words to longestWords and frequentWords. Each analysis receives the same word stream, so one can produce long words while the other calculates the most frequent words. section 9.2.5

How Learn Concurrent Programming with Go covers it

How deep it goes
Explains wake-all semantics, mutex coordination, missed notifications, and a generic channel implementation with slow-consumer behavior.
Examples
Uses a four-player game, a custom waitgroup reaching zero, and word statistics sent to longest-word and frequency analyses.
What it assumes
Introduces Broadcast through goroutines, condition variables, mutexes, Wait, and channels rather than assuming synchronization terminology.
What you can do after
Build it from scratch as a mutex-protected wake-all operation or a generic channel replicator for multiple consumers.
How it connects
Connects condition variables, mutexes, Wait, Signal, waitgroups, channels, fan-in, fan-out, pipelines, and quit channels.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Concurrent Programming with Go. The section links point to the parts of the book it draws on.