Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two way communication through channels in golang

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?

like image 695
shidsun Avatar asked Oct 14 '25 18:10

shidsun


1 Answers

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 chans :), 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 chans.

As the motto goes,

Do not communicate by sharing memory; instead, share memory by communicating.

like image 107
Nevermore Avatar answered Oct 17 '25 12:10

Nevermore



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!