Source file src/runtime/race/testdata/rwmutex_test.go

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package race_test
     6  
     7  import (
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  func TestRaceMutexRWMutex(t *testing.T) {
    14  	var mu1 sync.Mutex
    15  	var mu2 sync.RWMutex
    16  	var x int16 = 0
    17  	_ = x
    18  	ch := make(chan bool, 2)
    19  	go func() {
    20  		mu1.Lock()
    21  		defer mu1.Unlock()
    22  		x = 1
    23  		ch <- true
    24  	}()
    25  	go func() {
    26  		mu2.Lock()
    27  		x = 2
    28  		mu2.Unlock()
    29  		ch <- true
    30  	}()
    31  	<-ch
    32  	<-ch
    33  }
    34  
    35  func TestNoRaceRWMutex(t *testing.T) {
    36  	var mu sync.RWMutex
    37  	var x, y int64 = 0, 1
    38  	_ = y
    39  	ch := make(chan bool, 2)
    40  	go func() {
    41  		mu.Lock()
    42  		defer mu.Unlock()
    43  		x = 2
    44  		ch <- true
    45  	}()
    46  	go func() {
    47  		mu.RLock()
    48  		y = x
    49  		mu.RUnlock()
    50  		ch <- true
    51  	}()
    52  	<-ch
    53  	<-ch
    54  }
    55  
    56  func TestRaceRWMutexMultipleReaders(t *testing.T) {
    57  	var mu sync.RWMutex
    58  	var x, y int64 = 0, 1
    59  	ch := make(chan bool, 4)
    60  	go func() {
    61  		mu.Lock()
    62  		defer mu.Unlock()
    63  		x = 2
    64  		ch <- true
    65  	}()
    66  	// Use three readers so that no matter what order they're
    67  	// scheduled in, two will be on the same side of the write
    68  	// lock above.
    69  	go func() {
    70  		mu.RLock()
    71  		y = x + 1
    72  		mu.RUnlock()
    73  		ch <- true
    74  	}()
    75  	go func() {
    76  		mu.RLock()
    77  		y = x + 2
    78  		mu.RUnlock()
    79  		ch <- true
    80  	}()
    81  	go func() {
    82  		mu.RLock()
    83  		y = x + 3
    84  		mu.RUnlock()
    85  		ch <- true
    86  	}()
    87  	<-ch
    88  	<-ch
    89  	<-ch
    90  	<-ch
    91  	_ = y
    92  }
    93  
    94  func TestNoRaceRWMutexMultipleReaders(t *testing.T) {
    95  	var mu sync.RWMutex
    96  	x := int64(0)
    97  	ch := make(chan bool, 4)
    98  	go func() {
    99  		mu.Lock()
   100  		defer mu.Unlock()
   101  		x = 2
   102  		ch <- true
   103  	}()
   104  	go func() {
   105  		mu.RLock()
   106  		y := x + 1
   107  		_ = y
   108  		mu.RUnlock()
   109  		ch <- true
   110  	}()
   111  	go func() {
   112  		mu.RLock()
   113  		y := x + 2
   114  		_ = y
   115  		mu.RUnlock()
   116  		ch <- true
   117  	}()
   118  	go func() {
   119  		mu.RLock()
   120  		y := x + 3
   121  		_ = y
   122  		mu.RUnlock()
   123  		ch <- true
   124  	}()
   125  	<-ch
   126  	<-ch
   127  	<-ch
   128  	<-ch
   129  }
   130  
   131  func TestNoRaceRWMutexTransitive(t *testing.T) {
   132  	var mu sync.RWMutex
   133  	x := int64(0)
   134  	ch := make(chan bool, 2)
   135  	go func() {
   136  		mu.RLock()
   137  		_ = x
   138  		mu.RUnlock()
   139  		ch <- true
   140  	}()
   141  	go func() {
   142  		time.Sleep(1e7)
   143  		mu.RLock()
   144  		_ = x
   145  		mu.RUnlock()
   146  		ch <- true
   147  	}()
   148  	time.Sleep(2e7)
   149  	mu.Lock()
   150  	x = 42
   151  	mu.Unlock()
   152  	<-ch
   153  	<-ch
   154  }
   155  

View as plain text