MenTaLguY wrote:
> On Tue, 12 Jun 2007 03:13:39 +0900, "Nasir Khan" <rubylearner / gmail.com> wrote:
>>        @@__ms_c_lock.synchronize { @__ms_lock = Mutex.new unless
>> @__ms_lock
>> } unless @__ms_lock
>>
>> What is the race condition...?
> 
> It's known as the "double-checked locking" antipattern.  Generally, anything like:
> 
>  unless @obj
>    @lock.synchronize do
>      unless @obj
>        @obj = Whatever.new
>      end
>    end
>  end
>  @obj.some_method
> 
> is wrong.  This is because (when dealing with real multi-threading --
> not a major issue in Ruby yet, but it soon will be!) we depend on
> locks not only for preserving the order of operations, but ensuring
> that each thread has a consistent view of memory.  For instance, when
> reading the instance variable @obj outside the protection of the
> lock, it is possible that a thread could @obj being non-null, but not
> seeing the effects of initializing the object until much later!

(...and later restated)
> For instance, if reading the instance variable @obj outside the
> protection of the lock, it is possible for a thread to see that @obj
> is non-null long before the effects of the object's initialize method
> have become visible to it!


So you're saying that, as the line

         @obj = Whatever.new

is executed, it is possible (in some ruby implementations, but not MRI 
1.8) that @obj will be assigned the Whatever instance *before* the #new 
call completes? (That does seem to be what the wikipedia entry is 
warning about.[1])

Scary! Your point that we should rely on the locking primitives for all 
access (and hope that they get the memory barrier right) is well taken. 
Which means always paying the sync cost:

   def obj
     @lock.synchronize do
       @obj ||= Whatever.new
     end
   end

I wonder if the following will be a more efficient alternative, or worse 
because of the singleton method:

   def obj
     @lock.synchronize do
       @obj = Whatever.new
       def self.obj
         @obj
       end
     end
     @obj
   end

I suppose that has the same problem, depending on implementation, in 
that the method definition could be reordered before the assignment...

[1] http://en.wikipedia.org/wiki/Double-checked_locking

-- 
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407