Synchronized attr_accessor

- Is it true for Ruby today?

Depends on which implementation of Ruby. For Ruby 1.8, with its green threads, no. For XRuby, yes. For JRuby, yes. For Rubinius, no. IronRuby, yes. Ruby.NET, yes. YARV/1.9, no.

- If not then will it ever be true in future?

It will be also be true of Rubinius once it adds support for native threads. It will also be true of YARV/1.9 if and when the Big Scheduler Lock is abandoned.

- Is there some text somewhere where Ruby memory model for interpreter
developers?

No. There probably ought to be.

- Since Ruby doesnt have a volatile keyword does it mean that all variable
access is essentially non-volatile?

Yes, but even the volatile keyword doesn't do what you expect. Despite widespread folklore, volatile by itself is _not_ sufficient to ensure thread safety -- you need to use operations which include memory barriers (generally by using the provided synchronization primitives).

Incidentally, the environments where double-checked locking actually works are also the ones where it gives the least performance gain.

-mental

···

On Tue, 12 Jun 2007 04:23:35 +0900, "Nasir Khan" <rubylearner@gmail.com> wrote:

While the comparison is against Java synchronization, does the
Mutex#synchronize has the same behavior as synchronized in Java?
I see the code under 1.8 and synchronize basically does -

# File lib/thread.rb, line 132
  def synchronize
    lock
    begin
      yield
    ensure
      unlock
    end
  end

The keyword "synchronized" in Java implies not just locking but perhaps more
importantly "synchronization" of the current thread's working memory with
heap. [JLS 17.4]
The argument that you gave for explicit locking before use, is perfectly
valid as long as the underlying memory model of the language does that
synchronization.
It is not clear to me how the above code implictly does that, this brings
back to my question about Ruby Language specifications.

I can understand the behavior of JRuby but how would the other Ruby
interpreters be implemented for such things?
If one were to implement a Ruby interpreter today where should he/she start
in the absence of a language spec? Take MRI as the spec? But MRI may not be
addressing all the issues like the one in question here.

Am I missing something?

Yes, but even the volatile keyword doesn't do what you expect. Despite
widespread folklore, volatile by itself is _not_ sufficient to ensure thread
safety -- you need to use operations which include memory barriers
(generally by using the provided synchronization primitives).

BTW the folklore is codified as JLS v3 and is available since Java 5. (JSR
133 fixed in 2004)

"A write to a volatile variable
(§8.3.1.4)<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#36930&gt;
*v* synchronizes-with all subsequent reads of *v* by any thread (where
subsequent is defined according to the synchronization order)."
also see
http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
"Under the new memory model, accesses to volatile variables cannot be
reordered with each other or nonvolatile variable accesses. Writing to a
volatile field has the same memory effect as a monitor release, and reading
from a volatile field has the same memory effect as a monitor acquire. In
effect, because the new memory model places stricter constraints on
reordering of volatile field accesses with other field accesses, volatile or
not, anything that was visible to thread A when it writes to volatile field
f becomes visible to thread B when it reads f."

- Nasir

···

On 6/11/07, MenTaLguY <mental@rydia.net> wrote:

On Tue, 12 Jun 2007 04:23:35 +0900, "Nasir Khan" <rubylearner@gmail.com> > wrote:
> - Is it true for Ruby today?

Depends on which implementation of Ruby. For Ruby 1.8, with its green
threads, no. For XRuby, yes. For JRuby, yes. For Rubinius, no. IronRuby,
yes. Ruby.NET, yes. YARV/1.9, no.

> - If not then will it ever be true in future?

It will be also be true of Rubinius once it adds support for native
threads. It will also be true of YARV/1.9 if and when the Big Scheduler
Lock is abandoned.

> - Is there some text somewhere where Ruby memory model for interpreter
> developers?

No. There probably ought to be.

> - Since Ruby doesnt have a volatile keyword does it mean that all
variable
> access is essentially non-volatile?

Yes, but even the volatile keyword doesn't do what you expect. Despite
widespread folklore, volatile by itself is _not_ sufficient to ensure thread
safety -- you need to use operations which include memory barriers
(generally by using the provided synchronization primitives).

Incidentally, the environments where double-checked locking actually works
are also the ones where it gives the least performance gain.

-mental

While the comparison is against Java synchronization, does the
Mutex#synchronize has the same behavior as synchronized in Java?

Roughly speaking, yes.

I see the code under 1.8 and synchronize basically does -

# File lib/thread.rb, line 132
  def synchronize
    lock
    begin
      yield
    ensure
      unlock
    end
  end

The keyword "synchronized" in Java implies not just locking but perhaps
more importantly "synchronization" of the current thread's working memory with
heap. [JLS 17.4]

i.e. memory barriers.

It's probably better to compare Mutex#lock and Mutex#unlock with the JVM monitorenter and monitorexit instructions, since Java's synchronized translates to a single pair of monitorenter and monitorexit instructions on the JVM.

In JRuby, a call to each of #lock and #unlock involves both monitorenter and monitorexit, so Mutex#synchronize is actually slightly more aggressive than Java synchronized in terms of its memory effects. However, the portable assumption is probably still only that it is no less aggressive than the JVM.

I can understand the behavior of JRuby but how would the other Ruby
interpreters be implemented for such things?

In practice, implementors defer to whatever the underlying platform is; under those circumstances, the only option for programmers is to adopt a very conservative posture towards locking and memory model.

If one were to implement a Ruby interpreter today where should he/she
start in the absence of a language spec? Take MRI as the spec? But MRI may
not be addressing all the issues like the one in question here.

Indeed -- it doesn't. Though I suppose one could reasonably say that MRI, with its green threads, effectively fences all reads and writes, but that's obviously a bit heavy-handed to actually implement.

Yes, but even the volatile keyword doesn't do what you expect. Despite
widespread folklore, volatile by itself is _not_ sufficient to ensure
thread safety -- you need to use operations which include memory barriers
(generally by using the provided synchronization primitives).

BTW the folklore is codified as JLS v3 and is available since Java 5. (JSR
133 fixed in 2004)

That was badly needed (and I believe a similar fix was made in the CLR 2.0 memory model as well), but JRuby still targets Java 4, as does nearly all of other Java code I've been asked to work on professionally -- there's a bit of a gap between a JSR going in, and that Java version being widely adopted.

(Admittedly, I may be behind the curve Java 5 adoption, and I'm less sure about CLR 2.0 adoption as a whole.)

Anyway, for right now, this is a moot point in Ruby, since double-checked locking isn't possible to implement safely there; we have neither volatile (broken or otherwise), nor anything like .NET's System.Threading.Thread.MemoryBarrier(). The only way to get the required memory barriers in Ruby is to trust the library locking primitives to provide them when they are needed. The safe thing is to simply never to perform accesses to shared variables outside the protection of a lock, since that being safe is the minimum guarantee any locking implementation must provide.

-mental

···

On Tue, 12 Jun 2007 05:42:02 +0900, "Nasir Khan" <rubylearner@gmail.com> wrote: