I have several functions that I want them to be executed atomically since they deal with sensitive data structures. Suppose the following scenario:
There are two functions: lock(sth)
and unlock(sth)
that can be called anytime by a goroutine to lock or unlock sth
in a global array. I was thinking about having a command channel so that goroutines send lock
and unlock
commands into the channel, and on the receive side of the channel, some kind of handler
handles lock
, unlock
requests, sequentially, by grabbing commands from the channel. That's fine, but what if the handler
wants to send the result back to the requester? Is it possible to do so use golang channels? I know that it is possible to use some kind of lock mechanism like mutex, but I was wondering if it's possible to use channels for such use-case? I saw somewhere that it is recommended to use channel instead of goland low-level lock structs.
In a single sentence:
In a channel with the capacity of 1, I want the receiver side to be able to reply back to the goroutine which sent the message.
or equivalently:
A goroutine sends something to a channel; the message is received by another goroutine and handled leading to some result; how does the sender become aware of the result?
The sync
package includes a Mutex lock, sync.Mutex
, which can be locked and unlocked from any goroutine in a threadsafe way. Instead of using a channel to send a command to lock something, how about just using a mutex lock from the sender?
mutex := new(sync.Mutex)
sensitiveData := make([]string, 0)
// when someone wants to operate on a sensitiveData,
// ...
mutex.Lock()
operate(sensitiveData)
mutex.Unlock()
When you say how does the sender become aware of the result, I think you're talking about how does the handler receive the result -- that would be with a chan
. You can send data through channels.
Alternatively, if you just want to be aware, a semaphore, sync.WaitGroup
might do the job. This struct can be Add()
ed to, and then the sender can wg.Wait()
until the handler calls wg.Done()
, which will indicate to the sender (which is waiting) that the handler is done doing such and such.
If your question is about whether to use locks or channels, the wiki has a terse answer:
A common Go newbie mistake is to over-use channels and goroutines just because it's possible, and/or because it's fun. Don't be afraid to use a sync.Mutex if that fits your problem best. Go is pragmatic in letting you use the tools that solve your problem best and not forcing you into one style of code.
As a general guide, though:
Channel: passing ownership of data, distributing units of work, communicating async results
Mutex: caches, state
If you absolutely want to avoid anything but chan
s :), try not altering the sensitive array to begin with. Rather, use channels to send data to different goroutines, at each step processing the data, and then funneling the processed data into a final type goroutine. That is, avoid using an array at all and store the data in chan
s.
As the motto goes,
Do not communicate by sharing memory; instead, share memory by communicating.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With