Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon can you provide examples of using both channels and mutexes in a single Go program


can you provide examples of using both channels and mutexes in a single Go program


Yes, here are some examples of using both channels and mutexes in a single Go program:

Example 1: Using Channels and Mutexes for Synchronization

go
package main

import (
    "fmt"
    "sync"
)

var (
    ch = make(chan int, 1)
    mu sync.Mutex
    x  int
)

func increment() {
    mu.Lock()
    x++
    mu.Unlock()
    ch <- x
}

func main() {
    for i := 0; i < 1000; i++ {
        go increment()
    }
    for range make([]int, 1000) {
        fmt.Println(<-ch)
    }
}

In this example, we use a channel to communicate between goroutines and a mutex to protect the shared variable `x`. The `increment` function increments `x` and sends the new value through the channel. The main goroutine receives the values from the channel and prints them.

Example 2: Using Channels and Mutexes for Data Sharing

go
package main

import (
    "fmt"
    "sync"
)

var (
    ch = make(chan struct{}, 1)
    mu sync.Mutex
    data map[string]int
)

func producer() {
    mu.Lock()
    data["key"] = 10
    mu.Unlock()
    ch <- struct{}{}
}

func consumer() {
    <-ch
    fmt.Println(data["key"])
}

func main() {
    data = make(map[string]int)
    go producer()
    go consumer()
}

In this example, we use a channel to signal when the producer has finished writing to the shared map, and a mutex to protect the map from concurrent access. The producer writes to the map and sends a signal through the channel, and the consumer receives the signal and prints the value from the map.

Example 3: Using Channels and Mutexes for Error Handling

go
package main

import (
    "fmt"
    "sync"
)

var (
    ch = make(chan error, 1)
    mu sync.Mutex
    data map[string]int
)

func producer() {
    mu.Lock()
    data["key"] = 10
    mu.Unlock()
    ch <- nil
}

func consumer() {
    err := <-ch
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(data["key"])
    }
}

func main() {
    data = make(map[string]int)
    go producer()
    go consumer()
}

In this example, we use a channel to communicate errors between goroutines and a mutex to protect the shared map from concurrent access. The producer writes to the map and sends a signal through the channel, and the consumer receives the signal and prints the value from the map or handles any errors that occurred.

These examples demonstrate how you can use both channels and mutexes in a single Go program to achieve concurrency and synchronization.

Citations:
[1] https://go.dev/wiki/MutexOrChannel
[2] https://dev.to/adriandy89/concurrency-in-go-goroutines-mutexes-and-channels-40f4
[3] https://www.jaredfolkins.com/understanding-when-to-use-channels-or-mutexes-in-go/
[4] https://www.reddit.com/r/golang/comments/1bnabrl/hi_i_am_confused_why_do_buffer_channels_and_mutex/
[5] https://waytoeasylearn.com/learn/mutex-in-go/