Sourcebot logo
    /

    Channels vs. Mutexes

    Public (Read-only)

    Recent Chats

    Sign in to access your chat history.

    When should I use channels vs. mutexes? Find real usages of both and include them in your answer

    Answer

    In Go, both channels and mutexes are used for managing concurrency, but they serve different purposes and are suited for different scenarios.

    Mutexes (sync.Mutex)

    A mutex is used to protect a shared resource from being accessed by multiple goroutines at the same time. This is achieved by creating a critical section, a piece of code that only one goroutine can execute at any given time.

    When to use a mutex:

    • When you have a piece of state (like a variable, a struct, or a map) that multiple goroutines need to read from and write to.
    • When you want to ensure that a certain block of code is executed atomically, without interference from other goroutines.

    Example:

    In the github.com/kubernetes/kops repository, a sync.Mutex is used to protect a map of disks from concurrent access. The diskClient struct has a disks map and a sync.Mutex. Whenever a method on diskClient needs to access the disks map, it must first acquire the lock.

    disk.go:28-32

    1type diskClient struct {
    2 // disks are disks keyed by project, zone, and disk name.
    3 disks map[string]map[string]map[string]*compute.Disk
    4 sync.Mutex
    5}

    Channels

    Channels are a way for goroutines to communicate with each other. They provide a typed conduit through which you can send and receive values with the channel operator, <-.

    When to use a channel:

    • When you need to pass data from one goroutine to another.
    • When you need to coordinate the execution of multiple goroutines.
    • When you want to signal completion of a task from one goroutine to another.

    A common Go proverb is: "Don't communicate by sharing memory; share memory by communicating." This often means that it is better to use channels to pass data between goroutines rather than using a mutex to protect shared data.

    Example:

    In the github.com/MHSanaei/3x-ui repository, a channel is used to listen for operating system signals to gracefully shut down the application. The sigCh channel is created to receive os.Signal values. The signal.Notify function directs the specified signals to this channel. The main goroutine then blocks, waiting to receive a signal on the channel.

    main.go:68-72

    1 sigCh := make(chan os.Signal, 1)
    2 // Trap shutdown signals
    3 signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM)
    4 for {

    In another example from the github.com/kubernetes/kops repository, a channel is used to handle errors from a batch operation. The errs channel is created and passed to the batchPerform function, which runs in a separate goroutine. The main goroutine can then read from this channel to receive any errors that occur during the batch processing.

    client.go:568-572

    1 errs := make(chan error)
    2 go batchPerform(infos, fn, errs)
    3
    4 for range infos {

    Summary

    FeatureMutex (sync.Mutex)Channel
    PurposeProtect shared stateCommunication between goroutines
    AnalogyA lock on a roomA conveyor belt
    Use CaseGuarding critical sections of code that access shared dataPassing data and coordinating goroutines
    Go Proverb"Communicate by sharing memory" (less idiomatic)"Share memory by communicating" (more idiomatic)
    disk.go
    main.go
    client.go