| // 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 | |
| } | |