Stop a gouroutine after a period of time

Issue

Is it concurrent safe to Stop a gouroutine after a period of time, like this?

  1. Code: (Note: data race since ok changes in another goroutine):
package main

import (
    "fmt"
    "time"
)

func main() {
    var ok byte
    time.AfterFunc(1000*time.Millisecond, func() {
        ok = 1
    })

    var i uint64
    for ok == 0 {
        i++ // CPU intensive task
    }
    fmt.Println(i) // 2_776_813_033
}

Terminal:

go run -race .

==================
WARNING: DATA RACE
Write at 0x00c000132010 by goroutine 8:
  main.main.func1()
      ./main.go:11 +0x46

Previous read at 0x00c000132010 by main goroutine:
  main.main()
      ./main.go:15 +0xf4

Goroutine 8 (running) created at:
  time.goFunc()
      go/src/time/sleep.go:180 +0x51
==================
80849692
Found 1 data race(s)

  1. Code (No data race):
package main

import (
    "fmt"
    "sync/atomic"
    "time"
)

func main() {
    var ok int32
    time.AfterFunc(1000*time.Millisecond, func() {
        atomic.StoreInt32(&ok, 1)
    })

    var i uint64
    for atomic.LoadInt32(&ok) == 0 {
        i++ // CPU intensive task
    }
    fmt.Println(i) // 2_835_935_488
}

Terminal:

go run -race .

31934042

Solution

There is no guarantee that the busy-wait for loop will terminate even if ok is set to false by another goroutine. There is no explicit synchronization during the setting and reading of ok, so the main goroutine is not guaranteed to see the changes made to it. In other words, there is no way to establish a happened-before relationship between the two goroutines.

https://golang.org/ref/mem

Second version of the code is safe even though it is not stated in the Go memory model with respect to ok, but it is not safe because such tight loops may not allow other goroutines to execute. Atomic read/write has the memory barriers necessary for a happened-before relationship. You should use one of the synchronization primitives (mutex, channel) to guarantee that.

Answered By – Burak Serdar

Answer Checked By – Terry (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.