On Tuesday, August 23, 2016 at 6:14:19 PM UTC+8, Yulrizka wrote: > > Thank you for the explanation and the code sample > > But the case here is indeed as Marvin explained, There is race condition. >
Marvin says there is no race condition in your start comment. > But in my example, I make sure that wg done is to protect result pointer > before calling it to caller. > > with this structure some one could easily introduce a race condition if he > tried to access the result pointer. > > What I would like to understand if there is case that my snippet causes > race condition. > > This is my understanding. > 1. Heap memory is shared between go rountine in the same process > 2. main routine create a pointer to some struct on the heap (initially nil) > 3. the go routine allocate memory on the heap for the `foo` struct > 4. the go routine assign main's result pointer > 5. wg.Done() ensure that step 4 is done before it released > 6. process will always returns value generated by the go routine. > > And I would like to make sure that my understanding of heap is correct. > That is shared per process and there are no heap copying between go routine. > > Thanks for the response so far, It is really interesting discussion for me > :) > > On Monday, August 22, 2016 at 3:47:03 PM UTC+2, 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. >> >> -- 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.