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.

+3


source to share


1 answer


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.

+2


source







All Articles