From: Erwin Abbott Date: 2007-06-16T12:02:08+09:00 Subject: Re: Reasonable practice? On 6/15/07, Robert Dober wrote: > On 6/15/07, Trans 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