Dear gophers
I have discussion with my colleague about this code
func process() *foo {
var result *foo
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
result = &foo{1}
}()
wg.Wait()
return result
}
He argues that this is heap race condition.
the result variable which lives on the heap of the go routine is not guaranteed to be synced to the result on the process func's thread.The better approach would be using a channel instead. I may agree with him that probably using channel is better.
But I would like to understand the reasoning behind that.
I thought that `wg.Wait()` guaranteed that the process func's thread wait until go func is finsihed and sync everything so that the result variable is safe to return.
Probably I'm missing some knowledge about how go routine work.
1. Does the process func thread has separate heap than the go func? If so how does is sync?
2. From I read so far, when go routine needed a bigger stack, it allocates memory from the heap. So what happened for object that is allocated inside of the go routine once the go routine returns?
I there article of source that go into details about this I would love to read it :)
Warm regards,
-j
The code might be race free for the current Go implementation but I don't think this behaviour is documented.
https://golang.org/ref/mem doesn't mention sync.WaitGroup at all. So wg.Done() doesn't necessarily happen before wg.Wait() returns and the effect of writing to "result" could be not visible after wg.Wait().
-j
Dear gophers
I have discussion with my colleague about this code
func process() *foo {
var result *foo
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
result = &foo{1}
}()
wg.Wait()
return result
}
He argues that this is heap race condition.
the result variable which lives on the heap of the go routine is not guaranteed to be synced to the result on the process func's thread.The better approach would be using a channel instead. I may agree with him that probably using channel is better.like to understand the reasoning behind that.
But I would
WaitGroup?
Yes like Jan previously said. It is the very use case WaitGroup was developed for.
--
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.
For more options, visit https://groups.google.com/d/optout.
package main
import (
"fmt"
"sync"
)
func main() {
var i int
for {
r := process()
if r.v == 8 {
fmt.Printf("%d\n", i)
panic("eight!")
}
i++
}
}
type foo struct {
v int
}
func process() *foo {
var result *foo
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
result = &foo{1}
}()
// race condition on result
result = &foo{8}
wg.Wait()
return result
}If the OP's friend was trying to say that there easily could be a race
condition if the code was modified to access result in process() after
the go stmt but before the Wait, he would be correct, or if the OP did
not post the full code that his friend was talking about, there might
also be a race condition in the code his friend saw.
But the WaitGroup in the originally posted code does properly order the
two accesses to result.
...Marvin
Thank you for the explanation and the code sample
But the case here is indeed as Marvin explained, There is race condition.
-j