A mutex protects a shared map when more than one goroutine records metrics.

Mutex Metrics

mutex_metrics.go
package main

import (
	"fmt"
	"sync"
)

func main() {
	var hitsPerWorker = 
	metrics := map[string]int{"hits": 0}
	var lock sync.Mutex
	var wg sync.WaitGroup

	for worker := 0; worker < 2; worker++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for i := 0; i < hitsPerWorker; i++ {
				lock.Lock()
				metrics["hits"] = metrics["hits"] + 1
				lock.Unlock()
			}
		}()
	}

	wg.Wait()

	fmt.Println("hitsPerWorker=", hitsPerWorker)
	fmt.Println("hits=", metrics["hits"])
	fmt.Println("workers=", 2)
}
package main

import (
	"fmt"
	"sync"
)

func main() {
	var hitsPerWorker = 
	metrics := map[string]int{"hits": 0}
	var lock sync.Mutex
	var wg sync.WaitGroup

	for worker := 0; worker < 2; worker++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for i := 0; i < hitsPerWorker; i++ {
				lock.Lock()
				metrics["hits"] = metrics["hits"] + 1
				lock.Unlock()
			}
		}()
	}

	wg.Wait()

	fmt.Println("hitsPerWorker=", hitsPerWorker)
	fmt.Println("hits=", metrics["hits"])
	fmt.Println("workers=", 2)
}
package main

import (
	"fmt"
	"sync"
)

func main() {
	var hitsPerWorker = 
	metrics := map[string]int{"hits": 0}
	var lock sync.Mutex
	var wg sync.WaitGroup

	for worker := 0; worker < 2; worker++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for i := 0; i < hitsPerWorker; i++ {
				lock.Lock()
				metrics["hits"] = metrics["hits"] + 1
				lock.Unlock()
			}
		}()
	}

	wg.Wait()

	fmt.Println("hitsPerWorker=", hitsPerWorker)
	fmt.Println("hits=", metrics["hits"])
	fmt.Println("workers=", 2)
}
protected metrics Lock the shared map only around the update, then read it after all goroutines have joined.