sync: fix TestMutexConcurrent test

Accessing the same variable from multiple goroutines is unsafe, and will
fail with parallelism. A lightweight way to avoid issues is by using
atomic variables.
This commit is contained in:
Ayke van Laethem
2025-06-10 17:10:48 +02:00
committed by Ron Evans
parent 83de8ff77d
commit 525c41bac9
+11 -10
View File
@@ -58,9 +58,9 @@ func TestMutexUncontended(t *testing.T) {
// It will fail if multiple goroutines hold the lock simultaneously. // It will fail if multiple goroutines hold the lock simultaneously.
func TestMutexConcurrent(t *testing.T) { func TestMutexConcurrent(t *testing.T) {
var mu sync.Mutex var mu sync.Mutex
var active uint var active atomic.Uint32
var completed uint var completed atomic.Uint32
ok := true var fail atomic.Uint32
const n = 10 const n = 10
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
@@ -74,11 +74,11 @@ func TestMutexConcurrent(t *testing.T) {
mu.Lock() mu.Lock()
// Increment the active counter. // Increment the active counter.
active++ nowActive := active.Add(1)
if active > 1 { if nowActive > 1 {
// Multiple things are holding the lock at the same time. // Multiple things are holding the lock at the same time.
ok = false fail.Store(1)
} else { } else {
// Delay a bit. // Delay a bit.
for k := j; k < n; k++ { for k := j; k < n; k++ {
@@ -87,10 +87,11 @@ func TestMutexConcurrent(t *testing.T) {
} }
// Decrement the active counter. // Decrement the active counter.
active-- var one = 1
active.Add(uint32(-one))
// This is completed. // This is completed.
completed++ completed.Add(1)
mu.Unlock() mu.Unlock()
}() }()
@@ -104,10 +105,10 @@ func TestMutexConcurrent(t *testing.T) {
// Acquire the lock and check whether everything has completed. // Acquire the lock and check whether everything has completed.
mu.Lock() mu.Lock()
done = completed == n done = completed.Load() == n
mu.Unlock() mu.Unlock()
} }
if !ok { if fail.Load() != 0 {
t.Error("lock held concurrently") t.Error("lock held concurrently")
} }
} }