I believe you only need one or the other; I assumed a use case like this: https://play.golang.org/p/nSgyiXU87XN
On Sun, Apr 14, 2019 at 1:33 PM <michael.f.el...@gmail.com> wrote: > I found a good discussion in the FAQ that explains the problem clearly. > https://golang.org/doc/faq#methods_on_values_or_pointers > > I think the mutex is needed on the update function with or without the use > of sync/atomic. The atomic guards the Load and the Store but the func is > operating on the copy returned by Load. Seems to me it's vulnerable to > being pre-empted unless the entire read/modify/write sequence is guarded by > a mutex. > > On Sunday, April 14, 2019 at 2:20:02 PM UTC-4, Skip wrote: >> >> I don't know if it's documented or not. In the language reference you >> can see the rules for method calls: >> >> https://golang.org/ref/spec#Calls >> https://golang.org/ref/spec#Method_sets >> >> A hint might have been that object should have mutated, but it didn't. >> It's in a class of errors that becomes recognizable once you've been bitten >> by it. >> >> In the example you gave, use of mutex seems redundant to me; execution of >> func passed into update is already guarded by atomic. >> >> On Sun, Apr 14, 2019 at 9:51 AM <michae...@gmail.com> wrote: >> >>> Thanks, Skip. That fixes it. Is the need for a pointer receiver >>> documented somewhere? It's not something that even crossed my mind given >>> that the neither the compiler nor golint complained. I suppose it makes >>> sense if I think of func (x) foo(y) {} as being an alternate way of writing >>> func foo(x, y) {}. In that case, it's clear that a copy of x is being >>> passed since that's Go's default. >>> >>> While this topic is still alive, I'd like to ask a follow-on question: >>> Is the use of sync/atomic actually needed in this example or is it >>> sufficient to wrap all accesses in mutex Lock/Unlock (using the same mutex, >>> of course). >>> >>> >>> >>> On Sunday, April 14, 2019 at 12:08:55 PM UTC-4, Skip wrote: >>>> >>>> The receiver for load and update should be the original object not a >>>> copy. >>>> >>>> https://play.golang.org/p/XCZC0OVhGMa >>>> >>>> On Sun, Apr 14, 2019, 7:56 AM <michae...@gmail.com> wrote: >>>> >>>>> >>>>> https://play.golang.org/p/6aQYNjojyBD >>>>> >>>>> I'm clearly missing something about the way sync.Mutex and >>>>> atomic.Value work in Go. >>>>> >>>>> I'm attempting to write a pair of concurrency safe methods, load() and >>>>> update(), for accessing a struct. The struct is stored as an atomic.Value >>>>> and accessed with atomic.Load and atomic.Value. I'm also wrapping the >>>>> accesses within a mutex Lock/Unlock. That's probably unneeded for my >>>>> load() method but I added it trying to figure out why it's not returning >>>>> updated info. In my minimal example below (also in the Go Playground link >>>>> above) the output of main() should be: >>>>> >>>>> s={65535} >>>>> v={65535} >>>>> >>>>> but I get >>>>> >>>>> s={65535} >>>>> v={0} >>>>> >>>>> indicating that the updated value is not available after the call to >>>>> update(). >>>>> >>>>> The only thing I'm doing that's a little different from the examples >>>>> in the doc for sync/atomic is passing a function that takes a pointer to a >>>>> struct instance to my update function. I do that to make it easy to write >>>>> code that updates just a few items in the state struct (which in my real >>>>> application has many members instead of just one as shown here.) >>>>> >>>>> Apologies for wasting the group's time if I've overlooked a brain-dead >>>>> error, but I've been fooling with this for several hours now and can't see >>>>> why it shouldn't be working, >>>>> >>>>> >>>>> package main >>>>> >>>>> import ( >>>>> "fmt" >>>>> "sync" >>>>> "sync/atomic" >>>>> ) >>>>> >>>>> type state struct { >>>>> R4000 uint16 >>>>> } >>>>> type guardedState struct { >>>>> v atomic.Value >>>>> } >>>>> >>>>> var stateMutex = sync.Mutex{} >>>>> var gState guardedState >>>>> >>>>> func init() { >>>>> gState.v.Store(state{}) >>>>> } >>>>> >>>>> func (g guardedState) load() state { >>>>> stateMutex.Lock() >>>>> defer stateMutex.Unlock() >>>>> s := gState.v.Load() >>>>> return s.(state) >>>>> } >>>>> >>>>> func (g guardedState) update(f func(*state)) { >>>>> stateMutex.Lock() >>>>> defer stateMutex.Unlock() >>>>> s := g.v.Load().(state) >>>>> f(&s) >>>>> g.v.Store(s) >>>>> } >>>>> >>>>> func main() { >>>>> f := func(s *state) { >>>>> s.R4000 = 65535 >>>>> fmt.Printf("s=%v\n", *s) >>>>> } >>>>> gState.update(f) >>>>> v := gState.load() >>>>> fmt.Printf("v=%v\n", v) >>>>> } >>>>> >>>>> -- >>>>> 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 golan...@googlegroups.com. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> -- >>> 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 golan...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- > 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. > -- 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.