On Monday, August 22, 2016 at 9:47:03 PM UTC+8, Joubin Houshyar wrote: > > > > On Saturday, August 20, 2016 at 2:29:41 AM UTC-4, Yulrizka wrote: >> >> 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, >> > > Your firend is correct that using a WaitGroup here does not in anyway > address concurrent access to the heap variable 'result'. > > This modified example should clear it up: > > 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 > } > > The issue here is the runtime scheduler and what execution order can occur > before the go routine execution 'process' has been stopped at wg.Wait. So > process can return a foo initiazed with either 1 or 8. > > I think the general Go developer intuiton here is that the go routine will > not run until the parent go routine has hit the wg.Wait (since there are no > explicit IO or blocking instructions between the go func() and wg.Wait. > However, using Go(1.7) the main loop will panic after as little as 1000 > loops. >
golang not fun. -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.