Hello, I'm Ganesh. I'm working on FreeDevTools online, currently building a single platform for all development tools, cheat codes, and TL; DRs — a free, open-source hub where developers can quickly find and use tools without the hassle of searching the internet.
If you are implemeting go routines, you should be aware of race conditions. How they can cause unexpected behavior and how to fix them.
What Is a Race Condition?
A race condition is a software or hardware flaw where a system's behavior depends on the unpredictable timing or sequence of uncontrollable events
The hardware level race condition is when one logic gate depends on the output of another logic gate, and both are in the same clock cycle.
From Diagram, we can see that the output of the first logic gate depends on the input of the second logic gate, and both are in the same clock cycle. This causes delay in the output of the final logic gate.
Similarly, in software, if two or more goroutines try to read and write the same variable without control, it can cause unexpected behavior. Causing the program to behave in an unexpected way.
Let’s start with a basic example where a race condition will not occur:
package main
import "fmt"
func main() {
counter := 0
counter++
fmt.Println("Counter:", counter)
}
This above code will not cause a race condition because we are using only one goroutine.
Output:
Counter: 1
The variable counter is incremented safely. But when we add goroutines, things can go wrong.
Introducing Goroutines
Now, let’s add goroutines to increment a shared variable. This is where race conditions start to appear.
This totaly depends on how many cores your CPU has.
If you have a single core, it will cause a race condition. But if you have multiple cores, it will not cause a race condition until the number of cores is equal to the number of goroutines.
package main
import (
"fmt"
"time"
)
func increment(counter *int) {
*counter++
}
func main() {
counter := 0
go increment(&counter) // First goroutine
go increment(&counter) // Second goroutine
time.Sleep(time.Second) // Wait for goroutines to finish
fmt.Println("Counter:", counter)
}
Output (may vary depending on number of cores your machine has):
Counter: 1
or
Counter: 2
We expect counter to be 2, but sometimes it’s 1.
The goroutines are racing to update counter.
One might overwrite the other’s change because there’s no coordination.
This is a called Counter: 2 condition.
Conclusion
By this we understood that race conditions can occur when multiple goroutines access and modify the same variable without proper synchronization.
In next part, we will learn how to find race conditions and how to fix them.
I’ve been building for FreeDevTools.
A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction when searching for tools and materials.
Any feedback or contributions are welcome!
It’s online, open-source, and ready for anyone to use.
👉 Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools


Top comments (0)