Francisco Pizarro
Francisco Pizarro

Reputation: 45

Understanding a Go race condition example from the official blog

I'm reading through https://blog.golang.org/race-detector and I'm not fully convinced of why Example 1 is a race condition. The following is an excerpt of the code with a race condition (lines 14-16):

11 func main() {
12     start := time.Now()
13     var t *time.Timer
14     t = time.AfterFunc(randomDuration(), func() {
15         fmt.Println(time.Now().Sub(start))
16         t.Reset(randomDuration())
17     })
18     time.Sleep(5 * time.Second)
19 }
20 
21 func randomDuration() time.Duration {
22     return time.Duration(rand.Int63n(1e9))
23 }

The blog post goes on to give this explanation for why there is a race condition:

If the initial timer duration is very small, the timer function may fire before the main goroutine has assigned a value to t and so the call to t.Reset is made with a nil t.

I'm not following why the duration matters for the return value. Even if time.AfterFunc is running in a separate goroutine, wouldn't it provide a return value before going on to execute its code? What changes given a sufficiently long duration where the return value is populated?

Upvotes: 0

Views: 243

Answers (1)

Burak Serdar
Burak Serdar

Reputation: 51577

In the given example, the following execution is possible:

  1. call time.AfterFunc()
  2. time.AfterFunc() starts a goroutine that waits for the timer to strike. time.Afterfunc continues running.
  3. timer strikes, calls the afterfunc
  4. afterFunc call t.Reset -> panic, because t will be set at step 5
  5. call to time.AfterFunc() returns, sets t

Upvotes: 2

Related Questions