Goruts or locks for concurrent clients
Often when writing concurrent programs with multiple goroutines, these goroutines require client access, for example to write a REST API where each HTTP handler must use a single initialized Redis client to read and write to the Redis instance.
I either have a client instance with a mutex blocking, so only one goroutine can use it at any given time, or have a client goroutine that other goruses can request to read through the pipe. Both work, but I'm wondering which is more idiomatic? Thank you for your help.
source to share
If you only have one client and only simple operations for it, use a mutex. This is typically simple and easy to understand, unlike a goroutine with a bunch of channels and select statements. Be sure to encapsulate thread safety to avoid burdening the API user with locks.
For comparison:
var (
mutex sync.Mutex
resource = 0
)
func Inc() int {
mutex.Lock()
defer mutex.Unlock()
resource++
return resource
}
FROM
var requests = make(chan chan int)
func init() {
go func() {
resource := 0
for {
response := <- requests
resource++
response <- resource
}
}()
}
func Inc() int {
response := make(chan int)
requests <- response
return <-response
}
The first is clearly more concise and easier to maintain. And especially if the resource is not global, the pipe approach also requires manual control of the gutters, since goroutines are not garbage collected (see how to stop a goroutine ).
If you don't mind having more than one client, use a client pool. go-redis supports merging out of the box. The pool itself is thread safe and can be used to get one of the idle connections.
source to share