7

From past work in C# and Java, I am accustomed to a statement such as this not being thread-safe:

x += y;

However, I have not been able to observe any collision among threads when running the above code in parallel with Ruby.

I have read that Ruby automatically prevents multiple threads from writing to the same data concurrently. Is this true? Is the += operator therefore thread-safe in Ruby?

Dan Tao
  • 125,917
  • 54
  • 300
  • 447

2 Answers2

2

Well, it depends on your implementation and a lot of things. In MRI, there is a such thing as the GVL (Giant VM Lock) which controls which thread is actually executing code at a time. You see, in MRI, only one thread can execute Ruby code at a time. So while the C librarys underneath can let another thread run while they use CPU in C code to multiply giant numbers, the code itself can't execute at the same time. That means, a statement such as the assignment might not run at the same time as another one of the assignments (though the additions may run in parallel). The other thing that could be happening is this: I think I heard that assignments to ints are atomic on Linux, so if you're on Linux, that might be something too.

Linuxios
  • 34,849
  • 13
  • 91
  • 116
  • Any idea if the GIL will ever be dropped for a thread in the middle of executing `x += y`? Or is it only ever acquired and released on _statement_ boundaries? Or higher-level boundaries? – sarnold Jun 27 '12 at 23:25
  • A very details answer to threads in general can be found at http://stackoverflow.com/questions/56087/does-ruby-have-real-multithreading. – Chris Jun 28 '12 at 21:17
  • @sarnold: The release of the GVM all depends on the underling C code. For example, in the implementation of `Bignum` multiplication, if the numbers are outside of a certain size, the GVL will be released so that other *Ruby* code can execute while the C multiples the numbers. The GVL is only really of concern to you if you develop C extensions though. – Linuxios Jun 28 '12 at 22:16
  • @Ckhrysze: The only real way to get parallelism in MRI Ruby is to use multiple processes. Other implementations such as JRuby, Rubinus, MacRuby, and IronRuby often provide real concurrency based on the concurrency of the underlying platform (Java, C, Objective-C, and .NET). – Linuxios Jun 28 '12 at 22:18
  • @Linuxios: Excellent; so, one might notice concurrency problems if one is performing `x *= y` often enough to run into `Bignum`. Fair enough. :) – sarnold Jun 28 '12 at 22:19
  • 1
    @sarnold: Not necessarily. It is *possible* that you would be fine, but for the most, part, always use mutexes when dealing with shared variables. Relying on technicalities and small details will not leave you so happy later. – Linuxios Jun 28 '12 at 22:55
0
x += 1

is equivalent in every way to

x = x + 1

(if you re-define +, you also automatically redefine the result of +=)

In this notation, it's clearer this is not an atomic operation, and is therefore not guaranteed thread-safe.

djconnel
  • 441
  • 2
  • 4
  • I understand that `+=` uses the `+` operator. I suppose I should have narrowed my question down to just integer addition, since that's the case that's got me most curious. I would be interested to know what gives you such confidence in this answer, though. As I said, I am familiar with C# and Java, where what you say is true. But thus far I have not seen evidence of this using MRI; and in fact what I *have* been able to find (such as the article I've linked to in the question) seems to suggest the contrary. I guess what I'm saying is a reference would be much appreciated :) – Dan Tao Jun 28 '12 at 20:29
  • Are you confident no other thread of execution can update `x` between the time its value is retrieved and before the new value is written? – sarnold Jun 28 '12 at 22:20