Understanding Sync Mutex and Atomic Locks in Go: When to Use Each

Adam Szpilewicz
5 min readMay 9, 2023
Photo by Georg Bommeli on Unsplash

Concurrency is an essential aspect of Go programming, and with it comes the challenge of ensuring that your data remains consistent across multiple goroutines. To achieve this, Go provides two primary mechanisms for synchronization: sync.Mutex and atomic locks. In this article, we will explore the differences between these two mechanisms, discuss when to use each, and provide examples to help you make the right choice for your specific use case.

Sync Mutex

A sync.Mutex (short for “synchronization mutex”) is a simple locking mechanism that ensures that only one goroutine can access a shared resource at a time. When a goroutine acquires a Mutex lock, other goroutines attempting to acquire the lock will block until the lock is released. Sync.Mutex is suitable for cases where you have complex data structures or when multiple operations need to be performed atomically.

package main

import (
"fmt"
"sync"
)

type BankAccount struct {
balance int64
mu sync.Mutex
}

func (a *BankAccount) Deposit(amount int64) {
a.mu.Lock()
a.balance += amount
a.mu.Unlock()
}

func (a *BankAccount) Withdraw(amount int64) error {
a.mu.Lock()
defer a.mu.Unlock()

if a.balance < amount {
return fmt.Errorf("insufficient funds")
}

//Adding random sleep to increase the chance of a race…

--

--

Adam Szpilewicz

Backend software engineer working with golang and python @Rivery (https://rivery.io/). I like writting and reading about code and software engineering.