Live data from Hacker News

Ruby core classes aren't thread safe

jstorimer.com

1–10 of 47 posts

Re: Ruby core classes aren't thread safe

#2
Nice write-up. It's easy to fall into the trap of assuming that things are "thread-safe" when writing under the iron fist of a Global Interpreter Lock.

Ruby threads seems to be a fairly narrow topic on which to base a book; I'll look forward to seeing what all the book covers.

Re: Ruby core classes aren't thread safe

#6
post #4

Does ruby have a spec? If not, I don't really see this as a problem... synchronization, especially in a dynamic language that's already really slow, would just add more overhead.

It does, though it's the sort that's mainly derived from the canonical implementation -- see RubySpec.

Re: Ruby core classes aren't thread safe

#7
Under the semantics described here, Java or C# core classes aren't "thread-safe" either and I'd expect the vast majority of standard libraries to completely fail the test (potential winners: Clojure using an immutable collection bound on an atom, as they have compare-and-swap semantics; and probably Haskell somehow), the example code requires performing the following actions atomically:

* Loading an instance-local collection

* Fetching a numeric value from the collection

* Incrementing or decrementing the numeric value

* Putting the incremented value back

Even if the collection is "synchronized" (each method call takes a collection-local lock), because the value is altered outside the collection there's no way for the change to be atomic unless it's wrapped in a transaction block or protected by a lock. As far as I can think, the only ways for core classes to "be thread-safe" considering the example (keeping mutable collections semantics) would be to either have collections dedicated specifically to the operation such as Java6's AtomicIntegerArray (http://docs.oracle.com/javase/6/docs/api/java/util/concurren...), or to have the collection apply the operation internally e.g. Hash#apply(key, &operation) used roughly like this:

    def decrease item
      @stock.apply(item) {|from| from - 1}
    end

Re: Ruby core classes aren't thread safe

#9
post #5

This still doesn't explain why the MRI implementation is accidentally threadsafe. Why doesn't the interpreter switch threads after reading the value from the hash but before storing the updated value?

Due to the Global Interpreter Lock (GIL), your whole script is wrapped in one giant mutex. That means that you don't have code running in true parallel, so the data is not corrupted as it is in JRuby and Rubinius (which both implement real, true, parallel threads).

Re: Ruby core classes aren't thread safe

#10
post #5

This still doesn't explain why the MRI implementation is accidentally threadsafe. Why doesn't the interpreter switch threads after reading the value from the hash but before storing the updated value?

If it's like CPython, the interpreter will release the GIL on IO or after a number of "ticks", but "ticks" are very loosely mapped to an expression or statement. So it will generally put all of (get value at index, increment value, store value) under a single lock.

So I'd expect that even on MRI the original code could in fact fail to yield 0 once in a while. That's what'd happen on CPython

Post reply on HN