Race condition is a common problem in Golang. A race condition is a situation where there are several requests simultaneously and depending on the time sequence of events, which can cause damage to the system process. In this article, we will cover how to handle race conditions in Golang using mutex and channel.
Normal Condition
package main
import (
"fmt"
"time"
)
type Counter struct {
value int
}
func (c *Counter) Increment() {
defer time.Sleep(time.Second) // simulate some work
c.value++
}
func main() {
var (
counter = Counter{
value: 0,
}
)
for i := 0; i < 1000; i++ {
counter.Increment()
}
fmt.Printf("Counter value is %d\n", counter.value)
}
Output:
note: code is include time sleep to simulate some work, then is running time is -+ 17 minutes (1 second * 1000 counting).
Race Condition
package main
import (
"fmt"
"sync"
"time"
)
type Counter struct {
value int
wg *sync.WaitGroup
}
func (c *Counter) Increment() {
defer time.Sleep(time.Second) // simulate some work
defer c.wg.Done()
c.value++
}
func main() {
var (
waitGroup sync.WaitGroup
counter = Counter{
wg: &waitGroup,
value: 0,
}
)
for i := 0; i < 1000; i++ {
waitGroup.Add(1)
go counter.Increment()
}
waitGroup.Wait()
fmt.Printf("Counter value is %d\n", counter.value)
}
Output:
Resolve Race Condition With Mutex
package main
import (
"fmt"
"sync"
"time"
)
type Counter struct {
value int
wg *sync.WaitGroup
mu *sync.Mutex
}
func (c *Counter) Increment() {
defer time.Sleep(time.Second) // simulate some work
defer c.wg.Done()
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func main() {
var (
waitGroup sync.WaitGroup
m sync.Mutex
counter = Counter{
wg: &waitGroup,
mu: &m,
value: 0,
}
)
for i := 0; i < 1000; i++ {
waitGroup.Add(1)
go counter.Increment()
}
waitGroup.Wait()
fmt.Printf("Counter value is %d\n", counter.value)
}
Output:
Resolve Race Condition With Channel
package main
import (
"fmt"
"sync"
"time"
)
type Counter struct {
value int
wg *sync.WaitGroup
ch chan bool
}
func (c *Counter) Increment() {
defer time.Sleep(time.Second) // simulate some work
defer c.wg.Done()
c.ch <- true
c.value++
<-c.ch
}
func main() {
var (
waitGroup sync.WaitGroup
ch = make(chan bool, 1)
counter = Counter{
wg: &waitGroup,
ch: ch,
value: 0,
}
)
for i := 0; i < 1000; i++ {
waitGroup.Add(1)
go counter.Increment()
}
waitGroup.Wait()
fmt.Printf("Counter value is %d\n", counter.value)
}
Output:
Conclusion
Race condition is a common problem in Golang. In this article, we will cover how to handle race condition in Golang using mutex and channel.