Is "a,b=c,d" atomic? or do I need a Mutex?

Hi, I have two methods that could be called by different threads and
both use the same array:

def method1 object
MyModule.array << object
end

def method2
array, MyModule.array = MyModule.array, nil
end

Do I need a Mutex (#synchronize() method) here? I think the answer is
NOT since both actions in the array are “atomic”. Am I right?

2012/6/10 Iñaki Baz C. [email protected]:

Do I need a Mutex (#synchronize() method) here? I think the answer is
NOT since both actions in the array are “atomic”. Am I right?

Auto-reply: Yes, it’s atomic:

def test a,b ; $a, $b = a, b ; end
times = 10000000
t1 = Thread.new { 1.upto(times) do |i| test(i,i) end }
t2 = Thread.new { 1.upto(times) { raise “NOT EQUAL” if $a!=$b } }
t1.join
t2.join
puts “OK”

=> “OK”

It is atomic on MRI. It may or may not be on other interpreters, if
you care about them. (But probably should be as an element of the
syntax.)

Array#<< may or may not be atomic as well. (It is on MRI.)

– Matma R.

Appending to an array from many threads in an unsynchronized manner can
definitely raise a ConcurrentModificationException on JRuby

2012/6/10 Bartosz Dziewoński [email protected]:

It is atomic on MRI. It may or may not be on other interpreters, if
you care about them. (But probably should be as an element of the
syntax.)

Array#<< may or may not be atomic as well. (It is on MRI.)

Thanks, so I’ve no problem since I’m coding for MRI.

On Sun, Jun 10, 2012 at 7:52 PM, Iñaki Baz C. [email protected]
wrote:

2012/6/10 Bartosz Dziewoński [email protected]:

It is atomic on MRI. It may or may not be on other interpreters, if
you care about them. (But probably should be as an element of the
syntax.)

Array#<< may or may not be atomic as well. (It is on MRI.)

Thanks, so I’ve no problem since I’m coding for MRI.

Sorry, but I think this is the wrong attitude. Even MRI’s
implementation can change and the default should be to properly
synchronize access to shared resources - if only for documenting the
shared access. Note also that multiple threads may invoke #method2
which makes synchronization necessary even in absence of swapping.

Kind regards

robert

2012/6/11 Robert K. [email protected]:

Sorry, but I think this is the wrong attitude. Even MRI’s
implementation can change and the default should be to properly
synchronize access to shared resources - if only for documenting the
shared access. Note also that multiple threads may invoke #method2
which makes synchronization necessary even in absence of swapping.

In my case #method2 is private and is just called by the library and
always in the same thread (the thread in which a C event loop runs).

I do agree that, while in Ruby land, I should use a mutex (not
required right now since Array#<< and a,b=c,d are atomic, but this
could change). However I’m re-writing my #method1 and #method2 in C
so, for sure I don’t need mutex. Please correct me if I’m wrong.

Thanks a lot.

2012/6/11 Tony A. [email protected]:

On Mon, Jun 11, 2012 at 1:00 AM, Iñaki Baz C. [email protected] wrote:

I do agree that, while in Ruby land, I should use a mutex (not
required right now since Array#<< and a,b=c,d are atomic

Note that Array#<< isn’t atomic, it’s just that the GIL prevents contention
between threads so it never becomes a problem (until you try to use a Ruby
implementation without a GIL)

Well, since I’m coding a C extension for Ruby 1.9 MRI, I assume I can
rely on the GVL :slight_smile:

On Mon, Jun 11, 2012 at 1:00 AM, Iaki Baz C. [email protected]
wrote:

I do agree that, while in Ruby land, I should use a mutex (not
required right now since Array#<< and a,b=c,d are atomic

Note that Array#<< isn’t atomic, it’s just that the GIL prevents
contention
between threads so it never becomes a problem (until you try to use a
Ruby
implementation without a GIL)

On Sun, Jun 10, 2012 at 11:51 AM, Bartosz Dziewoński
[email protected] wrote:

It is atomic on MRI. It may or may not be on other interpreters, if
you care about them. (But probably should be as an element of the
syntax.)

I would not bet on it being atomic, since Ruby’s context-switch
boundaries are not formally defined. However, atomicity is only
important if you expect that a non-atomic assignment would produce
different results than an atomic one, which is unlikely in this case.

Of course, if it matters, you shouldn’t rely on this being atomic.

  • Charlie