Race Detector

  • Go provides race detector tool for finding race conditions in Go code.
  • Binary needs to be race enabled
  • When race behaviour is detected a warning is printed
  • Race enabled binary will 10 times slower and consume 10 times more memory.
  • Integration tests and load tests are good candidates to test with binary with race enabled.
# test the package
go test -race mypkg

# compile and run the program
go run -race mysrc.go

# build the command
go build -race mycmd

# install the package
go install -race mypkg

Exercises

go run - race concurrency/06_Sync_Package/exercises/07_race_problem.go 
948.57048ms
==================
WARNING: DATA RACE
Read at 0x00c000136018 by goroutine 8:
  main.main.func1()
      /Users/kimi/go/src/MyGoNote/concurrency/06_Sync_Package/exercises/07_race_problem.go:17 +0xd4

Previous write at 0x00c000136018 by main goroutine:
  main.main()
      /Users/kimi/go/src/MyGoNote/concurrency/06_Sync_Package/exercises/07_race_problem.go:15 +0x158

Goroutine 8 (running) created at:
  time.goFunc()
      /usr/local/Cellar/go/1.17.5/libexec/src/time/sleep.go:180 +0x49
==================
1.034536491s
1.701154081s
1.937634052s
2.225741529s
2.776342333s
3.409605905s
3.741838895s
3.926345687s
4.408004933s
Found 1 data race(s)
exit status 66

Problem

https://go.dev/play/p/p1zlAJyoAhh

package main

import (
    "fmt"
    "math/rand"
    "time"
)

//TODO: identify the data race
// fix the issue.

func main() {
    start := time.Now()
    var t *time.Timer
    t = time.AfterFunc(randomDuration(), func() {
        fmt.Println(time.Now().Sub(start))
        t.Reset(randomDuration())
    })
    time.Sleep(5 * time.Second)
}

func randomDuration() time.Duration {
    return time.Duration(rand.Int63n(1e9))
}

//----------------------------------------------------
// (main goroutine) -> t <- (time.AfterFunc goroutine)
//----------------------------------------------------
// (working condition)
// main goroutine..
// t = time.AfterFunc()  // returns a timer..

// AfterFunc goroutine
// t.Reset()        // timer reset
//----------------------------------------------------
// (race condition- random duration is very small)
// AfterFunc goroutine
// t.Reset() // t = nil

// main goroutine..
// t = time.AfterFunc()
//----------------------------------------------------

Solution

https://go.dev/play/p/IdgSE9tn3yM

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    start := time.Now()
    reset := make(chan bool)
    var t *time.Timer
    t = time.AfterFunc(randomDuration(), func() {
        fmt.Println(time.Now().Sub(start))
        reset <- true
    })
    for time.Since(start) < 5*time.Second {
        <-reset
        t.Reset(randomDuration())
    }
}

// return random duration between 0~1 seconds
func randomDuration() time.Duration {
    return time.Duration(rand.Int63n(1e9))
}
© Kimi Tsai all right reserved.            Updated : 2023-07-12 09:04:54

results matching ""

    No results matching ""

    results matching ""

      No results matching ""