blob: 39219e58ae7b09ef50c6ce4fb71a48a352af3f9a [file] [log] [blame]
// 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
}