On 6/15/07, Robert Dober <robert.dober / gmail.com> wrote:
> On 6/15/07, Trans <transfire / gmail.com> wrote:
> > It the following reasonable? How thread safe is it?
> >     ...
> >     def go
> >       @ary.each { |x|
> >         @type = x
> -------------------------> Problem, Thread 1 gets interrupted by Thread2
> -------------------------> Thread2 changes @type
> >         run
> >       }
> >     end
> >
> >     def run
> >      # maybe some work is being done here too?
---------------------------> Threads can also interrupt here and change @type
> >       puts type
> >     end
> >

Robert's right, and I added another place threads might step on
eachother. Since this is a simplification, if you're calling #type
more than once in the #run method, you might even get different values
within the #run method!  Like this:

def run
  puts type # => String
--------> another thread calls #go or does something otherwise to change @type
  puts type # => might be a different value now!
  puts type # => might be the 3rd different value returned by #type
end

I don't know anything about lockable properties (haven't heard of
them), but I think the best way to make your code thread safe is to
only using locally scoped variables.  Constants, instance, class,
global, etc variables will probably all require some sort of mechanism
to control access (mutex, semaphore, condition var, etc) if they're
values are being changed. Those mechanisms typically erode the
performance advantage of parallelizing your program because they spend
time checking if it's safe to change some variable, and spend time
waiting for a lock to open and whatnot. But when you need to use them
they are handy tools.

You'll probably have to deal with writing instance variables
somewhere, like #initialize but that doesn't typically cause thread
safety issues because it's only ever called once on an object. If you
only ever read those instance variables, you'll be mostly in the
clear. When you start changing the state of the object you have to be
careful.

In your example, you could remove the line @type = x; and change the
next line to: run(x). Then redefine #run accordingly. You'll notice
your example code doesn't really need to change the object's state to
get the job done, so just write it in a way that doesn't do that and
you'll be thread safe. You may or may not be able to apply that idea
to your actual non-example code though.

Regards,
Erwin