Mutex and Channel

Vincent Mok
3 min readAug 27, 2018

--

The post is inspired by one of the participants in my talk in a local meet up on last December 2017. I was giving a talk about “How to write highly scalable microservices in Golang”. I brought up an idea to use Mutex rather than a channel for a better performance. Confused by my statement and explanation, the participant I mentioned earlier asked a question “What are the best use cases suited for a Mutex then?”. Back then I didn’t have much experience yet using the Mutex, thus I answered: “If you want to have a simpler usage, use Mutex. Otherwise, use the channel”. Unsatisfied for my own answer, I’m going to cover the better version answer now (yes, after eight months) through this post.

Based on the story, the post is going to answer these questions
1. What is a Mutex?
2. What use cases where the Mutex shines?
3. What is a channel?
4. What problems where the Channel shines?

Mutex

Mutex or mutual exclusion data structure allows a state to be accessed one at a time. Several processes, e.g. goroutines can request access to shared resources, but only one granted a time. By having this mechanism, Mutex protects a shared resource from a race condition.

Mutex Visualization

A Mutex is perfect solution for:

  1. Use to protect the state or several assets.

Following is the code example that demonstrates the point

Use Mutex to protect the state

2. Best suited for cache invalidation.

A cache usually a shared resource which is used by several goroutines for doing their tasks thus vulnerable to a race condition, e.g. a cache for storing a token revocation list. You don’t want other goroutines to access your cache when another goroutine invalidating the cache.

Use Mutex on invalidating cache

Channel

Channel is a way for a goroutine to pass data references to other goroutines. The data can be read or write by the other goroutine who received it, thus you can think of it as passing ownership of data.

Goroutine Visualization

A channel is a perfect solution for:

  1. Passing data to another goroutine

Often a goroutine depends on another synchronous or asynchronous end process results, e.g. the main thread wait patiently for the game server to be spawned successfully before continuing creating a match for the user party. A channel is the best solution in order to solve this problem. You can see the example below.

Use channe for passing data to another goroutine

2. Helps you distributing tasks to goroutines.

If you have tasks that can be done in parallel, then a channel can help you. You can see code example below:

Distributing tasks to the Goroutines

3. Goroutine synchronization.

We can use a channel to notify us whether a goroutine is finished. The article here clearly explains the point.

Summary

As you have read, channel and mutex are the tools for achieving synchronization. Both have their own pros, cons and use cases. Even though Golang encourages us to use the channel, that doesn’t mean that you need to use a channel for solving any synchronization problem, e.g. you can use a channel in order to protect a state from a race condition, but it requires more effort than using Mutex.
A mutex is the best solution for state and cache protection from a race condition. Channel is the best solution for passing data to another goroutine, distributing tasks, and synchronizing goroutines.

Personal Note:

I love constructive feedback regarding my writing and the topic. So if you guys have any feedback for me, please leave it a comment! Thank you and see you at the next post!

--

--

Vincent Mok

Hi! I use Medium to talk about my obsession on ergonomic home office setup, programming, product and project management.