yes, It is a data race.
But the problem mentioned by op is not caused by data race.

On Tuesday, September 12, 2017 at 3:59:32 AM UTC-4, Konstantin Khomoutov 
wrote:
>
> On Wed, Sep 06, 2017 at 04:26:09AM -0700, T L wrote: 
>
> > > > It is just weird that the evaluation timing of *p is different to 
> other 
> > > expressions, such as, *p+0, *p*1, func()int{return *p}m etc. 
> > > 
> > > The value depends on a data race so it's entirely undefined in all 
> cases. 
> > > That the actual outcome then depends on trivial differences that may 
> affect 
> > > CPU loads/stores, instruction ordering, register usage, etc isn't 
> > > surprising. 
> > 
> > I don't think it is so complex. It is simply that gc adopts a different 
> > route for evaluate pointer dereference. 
>
> It's not complex, it's a simple data race. 
>
> In your code 
>
>     var num = 10 
>     var p = &num 
>
>     c := make(chan int) 
>
>     go func() { 
>         c <- func()int{return *p}() 
>     }() 
>
>     time.Sleep(time.Second) 
>     num++ 
>     fmt.Println(<-c) 
>
> two goroutines -- the main one and the one you spawned are accessing the 
> variable "num" concurrently without any synchronization. 
>
> Some assorted points to may be make this more clear: 
>
> * Sleeping for "just enough" time is not a form of synchronization. 
>
> * You might be driven away by using a function literal which is 
>   immediately executed but that's pretty much equivalent to just doing 
>
>     c <- *p 
>
>   which supposedly makes the data race over the variable "num" 
>   even more obvious. 
>
> * You might keep false assumption that function literals producing 
>   function values close over values -- that is, they work sort of as 
>   code templates.  This is wrong: they close over variables, so in your 
>   example the function value you're constructing before running it on 
>   a separate goroutine closes over the variable "p", not the value 
>   obtained by dereferencing it at the time of producing that function 
>   value. 
>
>
> To explain what happens, step by step, the statement 
>
>   go func() { 
>       c <- func()int{return *p}() 
>   }() 
>
> in your example: 
>
> 1) Creates a function value which is a closure consisting of the 
>    anonymous function 
>
>      func() { 
>        c <- func()int{return *p}() 
>      } 
>
>    and a reference to the variable "p" in the scope of the function 
>    main(). 
>
>  2) Spawns a goroutine and tells it to execute the function value 
>     created on the previous step. 
>
>  3) When run, the function executes the function value produced by 
>     the expression on the right side of the channel send statement. 
>
>     That function value is itself a closure, closing over the variable 
>     "p" in the scope of its lexical parent function -- the closure 
>     created on step 1. 
>
>     The pointer gets dereferenced and this action accesses the memory 
>     location "backing" the variable "num". 
>     The same memory is accessed concurrently from the main goroutine. 
>
> Since there is no synchronization done for _this_ access, you have 
> a data race.  The fact you have a channel send/receive has nothing 
> to do with regard to accessing the memory of the "num" variable 
> since both goroutines do it before attempting its respective channel 
> send/receive operations.  During that time, they may have being run on 
> different hardware CPUs or one of the goroutines might have no chance to 
> run at all.  Running on different CPUs involves a whole lot of 
> interesting problems, of which the most glaring are reordering of memory 
> accesses and coherence problems of CPU caches. 
>
> Please read [1, 2] and [3] (which is written by one of the Go core devs). 
>
> 1. http://preshing.com/20120515/memory-reordering-caught-in-the-act/ 
> 2. 
> http://preshing.com/20120710/memory-barriers-are-like-source-control-operations/
>  
> 3. 
> https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong
>  
>
>

-- 
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