Pop a Party in Concurrent Way
In this party, I have to compare the best solution to prepare the party using waitgroup and channel.
Ah, sweet summer breeze! What a waste it’d be if I didn’t throw a pool party! I can’t wait to meet all my friends.
Many preparations to be done, such as venue booking, check, invitation, check, food, hmm, durian es teler would make a great dessert, but I’m not sure if my friends could take the odor 😔 hence if any of them can’t take it I’ll switch to pineapple ice 🥳.
A sequential solution
Without any further ado, I call them one by one and ask about durian es teler being the main dessert.
I just texted my friend one by one, how long it took for calling 4 friends ? Run the full snippet here. Now imagine if I have 500 friends, probably I need a whole day waiting for the response which leaves me no time.
Want to save more time?
I am thinking of another way to save time. But how? Suddenly, a SMS from my telco notified me that I get bonus of 1000 free SMSes. Woah, that’s a jackpot! I sent all of my friends a message “would you like to have durian es teler as dessert for the upcoming party?”.
Ok! This is slightly better. I utilize the waitgroup which save more time than previous solution. Now all I need to do is just wait for all of them to reply to it. If you are curious how much time that saved please run the code here .
Could it be faster?
The solution above is much better, now I just need to wait until the last of them replies, but come to think of it, do I really need to?
I don’t think it’s worth to wait all day for them to reply therefore I will eliminate the durian es teler for dessert when one of them say “no for durian”
Awesome, with this channel based solution I can save more time for preparing the party. Please reveal the surprise here.
Why is this solution faster than using waitgroup? Let’s talk about technical things a bit 😅 .
Look at line 19, I added a condition to exit the process earlier when the desirable answer is fulfilled. But there is another problem, when the main goroutine exits, the spawned goroutines, which are still checking with my other friends, can’t return because when they eventually send the result to the channel, there’d be no consumer. This caused them to leak, which means they would hold on to resources such as memory. When this happens, the memory consumption will continuously build up, and the app eventually crashes. We don’t want it, right? So, we need to allow them to exit the goroutine once we receive the desired result.
The sample below utilizes a “stopCh”. As long as one “yes” answer is received, it’s closed. On the other hand, all spawned goroutines also poll the stopCh. This means that if any goroutine tries to send to dataCh after the main exits and gets stuck, the “<-stopCh” case will be unblocked and it will exit. This is because reading from a closed channel immediately returns. More explanation in Dave Cheney’s Channel Axioms. To run the full code just click https://go.dev/play/p/CaUL9Q5i_cT.
Conclusion
Implementing concurrency could be a consideration for handling numerous of independent tasks. Utilizing sync.WaitGroup is usually a good choice, but when early termination is feasible, channels can be the alternative. On top of that, always ensure all goroutines can exit to avoid the goroutine leak so you can pop your party with less worry!
Wait what ?? Less worry ?? How to be not worry at all? I called my teammate Jason to help me improve this solution (the article will publish soon) so I have no worries to pop the party!