Earlier quoted context omitted.
I'm not sure that's possible. If the first thread isn't explicitly synchronizing the memory, it won't even detect when the map was changed (made thread-safe) by the second thread! A half-solution could be using very lightweight synchronization (e.g. a MVar containing an unsynchronized map) that's later converted as you describe, but it would still incur some cynchronization overhead (even for single-threaded use).
You could use the existing hardware memory protection mechanism, if you can do that per-thread. Each thread allocates into memory protected from other threads by default, and on a page fault caused by access from another thread it's then moved into shared memory, and converted to concurrent if needed. You could then profile allocation sites so that if a map is frequently converted to concurrent, you then start alloca…
Are Go maps sensitive to data races?
61–70 of 81 posts
Re: Are Go maps sensitive to data races?
#62Earlier quoted context omitted.
> Since a concurrent map (aka. Dictionary aka. Hashtable) is a lot more complex and slow than a non concurrent one, it's very very unlikely that Go would ship with its standard map type being a concurrent one. It would be a huge waste. We should develop a system where maps are unsynchronised by default, but when you access them from a second thread they are then converted transparently by the runtime to a thread-safe…
You can't do that retroactively. And it would make performance very hard to reason about or measure.
Re: Are Go maps sensitive to data races?
#63Earlier quoted context omitted.
You could use the existing hardware memory protection mechanism, if you can do that per-thread. Each thread allocates into memory protected from other threads by default, and on a page fault caused by access from another thread it's then moved into shared memory, and converted to concurrent if needed. You could then profile allocation sites so that if a map is frequently converted to concurrent, you then start alloca…
But how would the first thread know when the map/data structure has been moved? I guess you could cause a page-fault in the first thread after the move, although that would rely on inter-CPU synchronizaiton of kernel memory maps...
Re: Are Go maps sensitive to data races?
#64Earlier quoted context omitted.
But how would the first thread know when the map/data structure has been moved? I guess you could cause a page-fault in the first thread after the move, although that would rely on inter-CPU synchronizaiton of kernel memory maps...
The same way a thread learns about an object being moved by the GC - change all the pointers to point to the new one when you move it. Do this in a safepoint so access to the object is not interrupted.
Although I could imagine a similar "signaling" mechanism, where each thread would periodically read a single snychronized variable, to check if there's any additional "re-synchronisation" work it needs to do. But I'm guessing that CPUs are implemented that way anyways.
Re: Are Go maps sensitive to data races?
#65Earlier quoted context omitted.
The same way a thread learns about an object being moved by the GC - change all the pointers to point to the new one when you move it. Do this in a safepoint so access to the object is not interrupted.
So... the second thread needs to wait for the GC in order to modify the map concurrently? I mean, it is an optimization for the most common case (single-threaded access), but it imposes a quite high penalty for concurrent access... Although I could imagine a similar "signaling" mechanism, where each thread would periodically read a single snychronized variable, to check if there's any additional "re-synchronisation"…
No nobody needs to wait for a GC, but we use the same mechanism that the GC does.
> Although I could imagine a similar "signaling" mechanism, where each thread would periodically read a single synchronised variable
And that's how the GC already works. Except instead of a variable normally a 'test' instruction is used on a page of memory, and instead of setting the variable, the permission on the page are changed triggering a page fault.
Re: Are Go maps sensitive to data races?
#66Earlier quoted context omitted.
You can't do that retroactively. And it would make performance very hard to reason about or measure.
Why not? If a GC can move an object, why can't I change its representation? We do this all the time for code - compiling and deoptimising in a JIT - why not for data as well?
Re: Are Go maps sensitive to data races?
#67Earlier quoted context omitted.
You say that, while also suggesting that Java's best effort ConcurrentModificationException (something that will be thrown if you're lucky ) is better. Suggests to me that you know just enough to be dangerous.
Java's ConcurrentModificationException shows up very quickly if you test at all (probably 99% of the time). It is very good at helping beginners not make these mistakes.
Re: Are Go maps sensitive to data races?
#68Earlier quoted context omitted.
You say that, while also suggesting that Java's best effort ConcurrentModificationException (something that will be thrown if you're lucky ) is better. Suggests to me that you know just enough to be dangerous.
Java's ConcurrentModificationException shows up very quickly if you test at all (probably 99% of the time). It is very good at helping beginners not make these mistakes.
There is nothing there to prevent the HashMap itself from corrupting completely with multiple writers, or from data racing while fetching single items on multiple threads.
So there is no way you can use the ConcurrentModificationException as a way of ensuring that your HashMap is actually working in a concurrent scenario, it only handles one scenario: reads, and even only reads when iterating.
Re: Are Go maps sensitive to data races?
#69Golang devs should have a look at Clojure and it's `core.async` library. It works very similarly to Go (heavily inspired by the good stuff), but all data structures are persistent, meaning you will never have problems with concurrent mutations (because there there are no mutations in the API, only internally). I recommend Go users to install the boot utility, and playing around with Clojure & core.async. These commun…
For instance, in Go making a blocking system call inside of a goroutine "just works" as Go will create additional goroutines as necessary. But if you do the equivalent in Clojure, you risk thread starvation.
"However if you are using go blocks and blocking IO calls you're in trouble. You will in fact often get worse performance than using threads (in the normal case) since you will quickly hog all the threads in the go block thread pool and block out any other work! ... Since the go block thread pool is quite small, it's easy to block all the threads and thus stopping all 'go processing'."[0]
Now there are some ways around this; I think that you can use promises for blocking IO inside of a Clojure coroutine. But this is one area where you don't have to worry about this kind of thing in Go, even if you do have to know that the default map implementation isn't thread safe. :)
[0] http://martintrojer.github.io/clojure/2013/07/07/coreasync-a...
Re: Are Go maps sensitive to data races?
#70Golang devs should have a look at Clojure and it's `core.async` library. It works very similarly to Go (heavily inspired by the good stuff), but all data structures are persistent, meaning you will never have problems with concurrent mutations (because there there are no mutations in the API, only internally). I recommend Go users to install the boot utility, and playing around with Clojure & core.async. These commun…
It's been a while since I used Clojure, so I apologize if what I'm saying is wrong or out of date. Having used both Clojure and Go there are some significant differences in how coroutines work in each. For instance, in Go making a blocking system call inside of a goroutine "just works" as Go will create additional goroutines as necessary. But if you do the equivalent in Clojure, you risk thread starvation. "However i…