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?

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

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"

···

2012/6/10 Iñaki Baz Castillo <ibc@aliax.net>:

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?

--
Iñaki Baz Castillo
<ibc@aliax.net>

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 Rex

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

···

On Sun, Jun 10, 2012 at 9:51 AM, Bartosz Dziewoński <matma.rex@gmail.com>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.)

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

-- Matma Rex

--
Tony Arcieri

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

···

2012/6/10 Bartosz Dziewoński <matma.rex@gmail.com>:

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.)

--
Iñaki Baz Castillo
<ibc@aliax.net>

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

···

On Sun, Jun 10, 2012 at 11:51 AM, Bartosz Dziewoński <matma.rex@gmail.com> 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.)

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

···

On Sun, Jun 10, 2012 at 7:52 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

2012/6/10 Bartosz Dziewoński <matma.rex@gmail.com>:

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.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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 Robert Klemme <shortcutter@googlemail.com>:

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.

--
Iñaki Baz Castillo
<ibc@aliax.net>

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 Mon, Jun 11, 2012 at 1:00 AM, Iñaki Baz Castillo <ibc@aliax.net> 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

--
Tony Arcieri

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

···

2012/6/11 Tony Arcieri <tony.arcieri@gmail.com>:

On Mon, Jun 11, 2012 at 1:00 AM, Iñaki Baz Castillo <ibc@aliax.net> 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)

--
Iñaki Baz Castillo
<ibc@aliax.net>