Menu

vInsert.nl

What am I even on about

Golang Mutexes

One big problem arises that kills our application under seemingly very obscure circumstances. So called “raceconditions” will break everything you love once things start to warm-up scale wise. Your code is suddenly exposed to multiple workers trying to read from/write to the same source. Causing problems that are VERY hard to locate and debug.

Lets demonstrate the problem a bit, we’re building a hitcounter for our website.

Running this code, you will find it outputs 1.
This is because we’re copying the counter value to a different chunk of memory, increment the counter on the copied version, then copy it back. The last goroutine to finish will set it back to 1, because when it grabbed the initial value of the counter it was 0.

Mutexes

These amazing things allow you to patch the most obvious forms of raceconditions efficiently and mostly effortless. Mutexes, are part of the sync package, which provides tooling for keeping goroutines in check. Mutexes specifically work by simply flipping a bit to determine if the resource itself is being used by something else. Lets fix the above code:

Now our Counter struct embeds a Mutex, and we can invoke the functions Lock and Unlock.
Lock will lock the Mutex, and if it’s already locked it will block the goroutine until the Mutex is Unlock-ed. Making it so that only a single goroutine can access the resource at a time. By far the easiest method is embedding the mutex on the resource itself. Then you should make sure everything that accesses the resource requires it to be Unlock-ed.

However, there is one thing you should note. If you don’t properly Unlock the resource afterwards, you block a goroutine indefinitely, causing a deadlock. So always ensure that your code always Unlocks the mutex.
Defer postphones execution until the goroutine is done, it basically tells the runtime “do this once done”. I always put a defer Unlock after locking a mutex, so I don’t have to follow code flow to figure out when/where it happens. It’s always executed when halting the process.

Let’s refine the corrected code a bit more:

Thanks for reading

Leave a Reply