Ah sorry I've missed that in the email. On Tuesday, August 23, 2016 at 12:48:04 PM UTC+2, T L wrote: > > > > 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.