On Sat, Sep 11, 2021 at 5:01 PM Michael Dwyer <michael.k.dw...@gmail.com> wrote:
> Presently working on a Data Race and have some questions on how to proceed. > The code example is a hypothetical mock up of the actual code under > review, but is a fair representation. > > The struct used by both functions is named Foo. > In the hypothetical, SomeFunc() reads variable from foo.bar, checking for > nil, > if nil SomeFunc() calls a Foo method Refresh(). > Foo method Refresh() calls function DoSomeCalc() assigned to foo.bar and > returned back to method SomeFunc() > > The race detector flags the read of foo.bar in method SomeFunc() in the if > statement, > and flags the write of foo.bar in method Refresh(). > > The problem I see is that in method SomeFunc() the if statement does a > read, > but it too also does an assignment to foo.bar. > > My initial thought is to add a sync.Lock() at the beginning of method > SomeFunc(), > followed by a defer sync.UnLock(), > that will be held until method SomeFunc() exists. > I state this because method SomeFunc() also does an assignment to variable > foo.bar. > So, a sync.RLock() would be insufficient to protect variable foo.bar > > My only concern is the call to method Refresh(), which also writes to > foo.bar. > > If my understanding is correct, this should work, because the lock is > initiated in method SomeFunc(), held to the exit of the method. > With the call to method Refresh() occurring within method SomeFunc() the > lock should protect variable foo.bar from other goroutines trying to update > this variable. > > Asking this question to confirm my thought process is correct. > If there is an edge case I missed, please advise. > > func (foo *Foo) SomeFunc() fields.SomeVariable { > if foo.bar == nil { <=== Race detector flags this > read > foo.bar = foo.ReFresh() > } > return foo.bar > } > > func (foo *Foo) ReFresh() fields.SomeVariable { > foo.bar = DoSomeCalc(foo) <=== Race detector flags this > write > return foo.bar > } > I know this is psuedo-code meant to illustrate the relevant aspect of your real code but I don't understand why you're assigning to foo.bar in the ReFresh() method as well as where you invoke this method in SomeFunc(). If that isn't a mistake introduced while writing the simplified example it suggests there are other problems beyond the data race. It also seems like you've omitted some important details about the real program since the race implies that ReFresh() is called from a goroutine other than the one executing SomeFunc(). -- Kurtis Rader Caretaker of the exceptional canines Junior and Hank -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CABx2%3DD-5t1Zb_OBgHJN%3DmDAQ%2BXCV2kmRZ3p%2B5E%2BPiP8ksNNRJA%40mail.gmail.com.