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.

Reply via email to