Ok so after getting away with using maps to share data between threads for a loooong time, I've finally seen the light and accepted that this is not safe.
In my case the threads in question are a painter thread and a mouse/keyboard event processing thread. They want to share data because obviously a mouse hitbox needs to match what is being drawn on the screen, unless you're going for a ux that drives your users insane :) Anyway as I said it's not safe to concurrently read and write a map; eventually this will result in a panic. Yet I'm stuck with a codebase that does this all over the place. So despite hating the thought of blocking either thread I did what any honest java-for-dayjob coder would do and resigned myself to hiding the maps behind an RWLock. Of course things are never that simple; adding locks to code that was not designed with them in mind is a good way to introduce deadlocks (particularly of the recursive-read-lock-while-other-thread-is-acquiring-write-lock variety). I made another change to address recursive lock acquisition, realised I missed a couple of shared maps and suddenly locking code was strewn all over my program; I got to the point of acquiring a read-lock every time the mouse moved before giving up in disgust. I thought about using an actual concurrent map, but giving up the builtin map's ease of use and well-typedness didn't thrill me. After some thought I came up with an alternative approach... TLDR; My shared structures are *mostly* read-only, in the sense that read operations are much more common than writes. I decided I can afford to change the writes so 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. I was pretty chuffed with this approach. It's clearly not the most efficient but it allowed me to solve the panic without risking deadlock. I'd be surprised if I'm the first person to come up with it, but I haven't seen it mentioned - the majority of advice seems to be "use an RWLock" or "use a concurrent map". I'm interested in understanding how safe/portable the approach is. I'm no expert on ARM/memory barriers but my understanding is that without an explicit sync/channel operation there's no guarantee another thread will see a change (in this case, the new map instance). In my case I have a channel based notification mechanism running alongside to wake up the painter thread when something changes, I'm just not sure what memory changes that is guaranteed to communicate. I also just wanted to share the approach and see how other people feel about it. It reminds me a bit of a double-buffering - writing to the backbuffer and then swapping it into action. -sqweek -- 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.