I think it is pretty common to make your map/list "read only" and to update
it by a replace.  That does not get you away from the need for a mutex,
however.   There is still a reader and writer:

Reader:

v := m[key]


Writer:

m = newMap


Those two operations are not safe together.  You still need a mutex:

mu.Lock()
mc := m
mu.Unlock()
v := mc[key]

mu.Lock()
m = newMap
mu.Unlock()


Of course, if you are not going to fetch multiple values from mc, it
degenerates to:

mu.Lock()
v := m[key]
mu.Unlock()


Which is what you are trying to avoid.

That said, a map is represented by a single machine word (32 or 64 bits).
I don't know of any modern architecture where reading a cache aligned word
while it is being written will yield anything but the old or new value.
The Go memory model does not guarantee this, however, so while it might
work for you now on your current target, that is a side effect of an
implementation and architecture detail.

There are some architectures that allow non-aligned reads/writes where a
machine word could span cache lines, but that is very expensive and I do
not believe Go ever generates code like that, though I guess it could be
possible.

    -Paul

On Mon, Sep 12, 2016 at 6:47 PM, Caleb Spare <cesp...@gmail.com> wrote:

> If you have a data race, you lose a lot of guarantees about the
> correct operation of your program. It may work today but fail
> occasionally, or a future version of the compiler may break it very
> badly.
>
> See https://software.intel.com/en-us/blogs/2013/01/06/benign-
> data-races-what-could-possibly-go-wrong.
>
> Most Go programmers consider programs with data races to be logically
> incorrect / broken.
>
> -Caleb
>
> On Mon, Sep 12, 2016 at 6:41 PM, sqweek E. <sqw...@gmail.com> wrote:
> > Thanks all. "Plain assignment" is not quite the full story actually - as
> I
> > mentioned originally there's also a channel in use to wake up the painter
> > thread. So in terms of memory model what I'm doing is more like:
> >
> >     x.myMap = newMap
> >     x.refresh <- nil // i don't think it matters what value is sent
> across
> > the channel?
> >
> > Also I don't mind a bit of racy non-determinism. If the painter thread
> > happens to be actively painting when I do this update I don't care if it
> > notices the newMap immediately or not, just as long as it sees the update
> > when painting the next frame. That will be after it has drained the
> refresh
> > channel, so should be guaranteed by the memory model if I've understood
> > correctly.
> >
> > For the general case sync.Value sounds appropriate. It means touching all
> > the reader code aswell, but in a fairly trivial way.
> >
> > Thanks again!
> > -sqweek
> >
> > On Tuesday, September 13, 2016 at 12:24:09 AM UTC+8, Peter Bourgon wrote:
> >>
> >> All memory operations are unsafe for concurrent goroutines unless
> >> explicitly noted otherwise. In practice, if you have multiple
> >> goroutines accessing the same memory, you need to protect it with the
> >> primitives available to you in package sync or sync/atomic. Please
> >> review https://golang.org/ref/mem for more details.
> >>
> >> Many Go programmers opt to sidestep these sorts of problems by using
> >> channels to orchestrate behavior and/or the flow of data between
> >> goroutines — i.e. not communicating by sharing memory, but rather
> >> sharing memory by communicating.
> >>
> >>
> >> On Mon, Sep 12, 2016 at 6:04 PM, sqweek E. <sqw...@gmail.com> wrote:
> >> > Yes, through plain assignment. What problems arise from that?
> >> >
> >> > On Monday, September 12, 2016 at 11:21:05 PM UTC+8, Peter Bourgon
> wrote:
> >> >>
> >> >> How are you replacing the reference to the original map? If you're
> >> >> just using plain assignment e.g. x.myMap = newMap then that's not
> >> >> safe. You could use sync/atomic.Value if you always made sure to do
> >> >> map reads via the Load method.
> >> >>
> >> >> On Mon, Sep 12, 2016 at 5:04 PM, sqweek E. <sqw...@gmail.com> wrote:
> >> >> > instead of updating the maps in place, they (a) take a
> >> >> > copy of the current map (b) update the copy and (c) replace the
> >> >> > reference to
> >> >> > the original map (held in a struct field) with the updated copy.
> >> >>
> >> > --
> >> > 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...@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.
>

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