<h2 id="Introduction">Introduction</h2>
<p>
-Data races are one of the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. See the <a href="/ref/mem">The Go Memory Model</a> for details.
+Data races are one of the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. See the <a href="/ref/mem/">The Go Memory Model</a> for details.
</p>
<p>
c := make(chan bool)
m := make(map[string]string)
go func() {
- m["1"] = "a" // First conflicting access.
+ m["1"] = "a" // First conflicting access.
c <- true
}()
- m["2"] = "b" // Second conflicting access.
+ m["2"] = "b" // Second conflicting access.
<-c
for k, v := range m {
fmt.Println(k, v)
<p>
The options are:
</p>
-<li><code>log_path</code> (default <code>stderr</code>): The race detector writes
+
+<ul>
+<li>
+<code>log_path</code> (default <code>stderr</code>): The race detector writes
its report to a file named log_path.pid. The special names <code>stdout</code>
and <code>stderr</code> cause reports to be written to standard output and
-standard error, respectively.</li>
-<li><code>exitcode</code> (default <code>66</code>): The exit status to use when
-exiting after a detected race.</li>
-<li><code>strip_path_prefix</code> (default <code>""</code>): Strip this prefix
-from all reported file paths, to make reports more concise.</li>
-<li><code>history_size</code> (default <code>1</code>): The per-goroutine memory
+standard error, respectively.
+</li>
+
+<li>
+<code>exitcode</code> (default <code>66</code>): The exit status to use when
+exiting after a detected race.
+</li>
+
+<li>
+<code>strip_path_prefix</code> (default <code>""</code>): Strip this prefix
+from all reported file paths, to make reports more concise.
+</li>
+
+<li>
+<code>history_size</code> (default <code>1</code>): The per-goroutine memory
access history is <code>32K * 2**history_size elements</code>. Increasing this
value can avoid a "failed to restore the stack" error in reports, but at the
-cost of increased memory usage.</li>
+cost of increased memory usage.
+</li>
+</ul>
<p>
Example:
package foo
// The test contains a data race. See issue 123.
-func TestFoo(t *testing.T) {
+func TestFoo(t *testing.T) {
// ...
}
// The test fails under the race detector due to timeouts.
-func TestBar(t *testing.T) {
+func TestBar(t *testing.T) {
// ...
}
// The test takes too long under the race detector.
-func TestBaz(t *testing.T) {
+func TestBaz(t *testing.T) {
// ...
}
</pre>
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
- fmt.Println(i) // Not the 'i' you are looking for.
+ fmt.Println(i) // Not the 'i' you are looking for.
wg.Done()
}()
}
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
- fmt.Println(j) // Good. Read local copy of the loop counter.
+ fmt.Println(j) // Good. Read local copy of the loop counter.
wg.Done()
}(i)
}
f1.Close()
}()
}
- f2, err := os.Create("file2") // The second conflicting write to err.
+ f2, err := os.Create("file2") // The second conflicting write to err.
if err != nil {
res <- err
} else {
</p>
<pre>
+ ...
_, err := f1.Write(data)
...
_, err := f2.Write(data)
+ ...
</pre>
<h3 id="Unprotected_global_variable">Unprotected global variable</h3>
<h3 id="Primitive_unprotected_variable">Primitive unprotected variable</h3>
<p>
-Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>), like in the following example:
+Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.), like in the following example:
</p>
<pre>
-type Watchdog struct { last int64 }
+type Watchdog struct{ last int64 }
func (w *Watchdog) KeepAlive() {
- w.last = time.Now().UnixNano() // First conflicting access.
+ w.last = time.Now().UnixNano() // First conflicting access.
}
func (w *Watchdog) Start() {
<p>
A typical fix for this race is to use a channel or a mutex.
-To preserve the lock-free behavior, one can also use the <a href="/pkg/sync/atomic"><code>sync/atomic</code></a> package.
+To preserve the lock-free behavior, one can also use the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package.
</p>
<pre>
-type Watchdog struct { last int64 }
+type Watchdog struct{ last int64 }
func (w *Watchdog) KeepAlive() {
atomic.StoreInt64(&w.last, time.Now().UnixNano())