# Is my code correct ? , I am trying to tackle the race condition problem safely using mutex and waitGroups

**URL:** <https://forum.golangbridge.org/t/is-my-code-correct-i-am-trying-to-tackle-the-race-condition-problem-safely-using-mutex-and-waitgroups/42022>\
**Category:** Code Review\
**Created:** [June 8, 2026, 11:56am UTC](https://forum.golangbridge.org/t/is-my-code-correct-i-am-trying-to-tackle-the-race-condition-problem-safely-using-mutex-and-waitgroups/42022 "2026-06-08T11:56:54Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![swap72](https://forum.golangbridge.org/user_avatar/forum.golangbridge.org/swap72/32/17558_2.png) [@swap72](https://forum.golangbridge.org/u/swap72)\
**Post date:** [June 8, 2026, 11:56am UTC](https://forum.golangbridge.org/t/is-my-code-correct-i-am-trying-to-tackle-the-race-condition-problem-safely-using-mutex-and-waitgroups/42022/1 "2026-06-08T11:56:55Z")

</div>

Please suggest correct / best approaches, solutions to this code :

```auto
func main() {
	var counter int
	var mu sync.Mutex
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		for i := 1; i <= 3000; i++ {
			mu.Lock()
			counter++
			mu.Unlock()
		}
		defer wg.Done()
	}()
	wg.Add(1)
	go func() {
		for i := 1; i <= 3000; i++ {
			mu.Lock()
			counter++
			mu.Unlock()
		}
		defer wg.Done()
	}()
	wg.Add(1)
	go func() {
		for i := 1; i <= 3000; i++ {
			mu.Lock()
			counter++
			mu.Unlock()
		}
		defer wg.Done()
	}()
	wg.Wait()
	fmt.Println(counter)
}

```

---

<div class="post-metadata">

**Author:** ![Dean\_Davidson](https://forum.golangbridge.org/user_avatar/forum.golangbridge.org/dean_davidson/32/9685_2.png) [@Dean\_Davidson](https://forum.golangbridge.org/u/Dean_Davidson)\
**Post date:** [June 8, 2026, 3:20pm UTC](https://forum.golangbridge.org/t/is-my-code-correct-i-am-trying-to-tackle-the-race-condition-problem-safely-using-mutex-and-waitgroups/42022/2 "2026-06-08T15:20:32Z")

</div>

I mean - what are you trying to do? In this specific instance, I would say take a look at the `sync/atomic` package. And specifically [`atomic.Int32`](https://pkg.go.dev/sync/atomic#Int32). From the `Add` method:

> Add atomically adds delta to x and returns the new value.

Atomics compile to low-level CPU instructions that are _very_ fast. I believe on x86 this is a single instruction. So, you could refactor your code to [this](https://go.dev/play/p/weaCodi9rGK):

```go
package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

func main() {
	var counter atomic.Int32
	var wg sync.WaitGroup
	const numWorkers, perWorker = 10, 3000
	wg.Add(numWorkers)
	for w := 0; w < numWorkers; w++ {
		go func() {
			defer wg.Done()
			for i := 1; i <= perWorker; i++ {
				counter.Add(1)
			}

		}()
	}
	wg.Wait()
	fmt.Println(counter.Load())
}

```

Nary a mutex in sight. OR - if you wanted to further refactor you could have each worker accumulate then send on a channel when complete with whatever unit of work they are doing:

```go
package main

import "fmt"

func main() {
	const numWorkers, perWorker = 10, 3000
	results := make(chan int, numWorkers)
	for w := 0; w < numWorkers; w++ {
		go func() {
			// Accumulate locally
			sum := 0
			for i := 1; i <= perWorker; i++ {
				sum++
			}
			// Send our result
			results <- sum
		}()
	}
	total := 0
	// Grab all results and total them
	for i := 0; i < numWorkers; i++ {
		total += <-results
	}
	fmt.Println(total)
}

```

That gives you more flexibility.

---

<div class="post-metadata">

**Author:** ![thequranclass](https://forum.golangbridge.org/letter_avatar_proxy/v4/letter/t/a6a055/32.png) [@thequranclass](https://forum.golangbridge.org/u/thequranclass)\
**Post date:** [November 15, 2026, 3:53pm UTC](https://forum.golangbridge.org/t/is-my-code-correct-i-am-trying-to-tackle-the-race-condition-problem-safely-using-mutex-and-waitgroups/42022/4 "2026-11-15T15:53:57Z")

</div>

Your code is race-free: the mutex protects `counter`, and `WaitGroup.Wait()` makes sure both goroutines finish before you read it, so the result will be correct.

Two practical notes:

1. Locking and unlocking on every increment is correct but slow — the mutex becomes the bottleneck. As Dean suggested, `atomic.Int32` is a good fit here, or give each goroutine its own local counter and add the two totals together at the end, so the workers never contend.

2. You can prove it to yourself by running it with the race detector: `go run -race main.go`. If there were a race on `counter`, it would report it, and with the mutex in place it should stay clean.
