Golang Concurrency #8 - Mutexes

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

Mutexes solve the problem: "What happens when multiple goroutines access the same variable?"
var counter int
func main() {
for i := 0; i < 1000; i++ {
go func() {
counter++ // Multiple goroutines modifying same variable
}()
}
time.Sleep(time.Second)
fmt.Println("Counter:", counter) // Should be 1000, but isn't!
}
Goroutine 1: Read counter (0) → Add 1 → Write back (1)
Goroutine 2: Read counter (0) → Add 1 → Write back (1)
Both read 0 at the same time, both write 1. We lost an increment!
var counter int
var mutex sync.Mutex
func main() {
for i := 0; i < 1000; i++ {
go func() {
mutex.Lock() // "I need exclusive access"
counter++ // Only one goroutine can do this at a time
mutex.Unlock() // "I'm done, others can proceed"
}()
}
time.Sleep(time.Second)
fmt.Println("Counter:", counter) // Now correctly prints 1000
}
Lock() - "Wait until no one else is using this, then it's mine"
Unlock() - "I'm done, next goroutine can have it"
Only one goroutine can hold the lock at a time
func increment() {
mutex.Lock()
defer mutex.Unlock() // Automatically unlock when function exits
counter++
// Even if panic happens, mutex gets unlocked
}
var data map[string]int
var rwMutex sync.RWMutex
func readData(key string) int {
rwMutex.RLock() // Multiple readers allowed
defer rwMutex.RUnlock()
return data[key]
}
func writeData(key string, value int) {
rwMutex.Lock() // Exclusive write access
defer rwMutex.Unlock()
data[key] = value
}
Protecting shared variables (counters, maps, slices)
When you need to update data structures
When channels would be overkill
Always pair Lock() with Unlock()
Use defer to ensure unlocking
Keep critical sections (locked code) small and fast
Prefer channels when possible, use mutexes when necessary