Why the following code is data race free ?

154 views
Skip to first unread message

Ting Yuan

unread,
Nov 17, 2021, 12:43:17 AM11/17/21
to golang-nuts
I wrote a simple function and hope it has a race alarm under the `-race` flag:

package main

import (
        "fmt"
        "time"
)

func main() {
        a := 1
        go func() {
                fmt.Println(a) // If I remove this instruction, the detector will report a data race
                a = 3
        }()
        fmt.Println(a)
        time.Sleep(time.Second)
}

I am confused, why there is no data race in the above program. I'm using go1.17.2 linux/amd64

Axel Wagner

unread,
Nov 17, 2021, 2:19:05 AM11/17/21
to Ting Yuan, golang-nuts
On Wed, Nov 17, 2021 at 6:43 AM Ting Yuan <yuanti...@gmail.com> wrote:
I am confused, why there is no data race in the above program. I'm using go1.17.2 linux/amd64

The race detector is a heuristic. That it doesn't report a race does not mean there is none. Races are non-deterministic, so it's very possible that any particular run just didn't trigger one.

This slightly modified version of the same race triggers the race-detector reliably for me:

func f() {
    wg := new(sync.WaitGroup)
    defer wg.Wait()

    a := 1
    wg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Print(a)
        a = 3
    }()
    fmt.Print(a)
}

func main() {
    for i := 0; i < 1000; i++ {
        f()
    }
}

I just added a bit of synchronization to replace the time.Sleep and called the code 1000 times, to increase the likelihood of triggering the race.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3833aa84-9614-4815-ba1b-700b2de51df8n%40googlegroups.com.

Axel Wagner

unread,
Nov 18, 2021, 2:43:44 AM11/18/21
to Ting Yuan, golang-nuts
[+golang-nuts again, please don't respond off-list. This is a public forum, everyone should benefit]

On Thu, Nov 18, 2021 at 3:47 AM Ting Yuan <yuanti...@gmail.com> wrote:
Thanks a lot, your code is very useful and explains my confusion. I think the underlying reason is because fmt.Println grabs a global mutex so it actually construct two critical section before the writing of a (i.e. a = 3). These critical section introduce a happens before relation so the race detector failed to report them. If the order of the two critical sections is reversed, the relation is broken and the race detector can alarm it.

You can verify that hypothesis by running this program under the race detector. It does the same thing and exhibits the same "occasionally racey" behavior as the original and lets you independently tinker with these ideas.
And yeah, after playing around for a bit, I think you are correct.
Reply all
Reply to author
Forward
0 new messages