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/