// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package race_test import ( "sync" "testing" "time" ) func TestRaceMutexRWMutex(t *testing.T) { var mu1 sync.Mutex var mu2 sync.RWMutex var x int16 = 0 _ = x ch := make(chan bool, 2) go func() { mu1.Lock() defer mu1.Unlock() x = 1 ch <- true }() go func() { mu2.Lock() x = 2 mu2.Unlock() ch <- true }() <-ch <-ch } func TestNoRaceRWMutex(t *testing.T) { var mu sync.RWMutex var x, y int64 = 0, 1 _ = y ch := make(chan bool, 2) go func() { mu.Lock() defer mu.Unlock() x = 2 ch <- true }() go func() { mu.RLock() y = x mu.RUnlock() ch <- true }() <-ch <-ch } func TestRaceRWMutexMultipleReaders(t *testing.T) { var mu sync.RWMutex var x, y int64 = 0, 1 ch := make(chan bool, 4) go func() { mu.Lock() defer mu.Unlock() x = 2 ch <- true }() // Use three readers so that no matter what order they're // scheduled in, two will be on the same side of the write // lock above. go func() { mu.RLock() y = x + 1 mu.RUnlock() ch <- true }() go func() { mu.RLock() y = x + 2 mu.RUnlock() ch <- true }() go func() { mu.RLock() y = x + 3 mu.RUnlock() ch <- true }() <-ch <-ch <-ch <-ch _ = y } func TestNoRaceRWMutexMultipleReaders(t *testing.T) { var mu sync.RWMutex x := int64(0) ch := make(chan bool, 4) go func() { mu.Lock() defer mu.Unlock() x = 2 ch <- true }() go func() { mu.RLock() y := x + 1 _ = y mu.RUnlock() ch <- true }() go func() { mu.RLock() y := x + 2 _ = y mu.RUnlock() ch <- true }() go func() { mu.RLock() y := x + 3 _ = y mu.RUnlock() ch <- true }() <-ch <-ch <-ch <-ch } func TestNoRaceRWMutexTransitive(t *testing.T) { var mu sync.RWMutex x := int64(0) ch := make(chan bool, 2) go func() { mu.RLock() _ = x mu.RUnlock() ch <- true }() go func() { time.Sleep(1e7) mu.RLock() _ = x mu.RUnlock() ch <- true }() time.Sleep(2e7) mu.Lock() x = 42 mu.Unlock() <-ch <-ch }