From: Robert Klemme Date: 2005-12-28T06:37:53+09:00 Subject: Re: Thread synchronization: Mutex or Monitor?? Bill Kelly wrote: > From: "Robert Klemme" >> >> I recommend to *not* use Thread.critical and Thread.exclusive (which >> uses #critical internally) for several reasons: >> >> - they limit concurrency more than necessary there is only a single >> lock which will prevent all but one thread from executing >> >> - I view them as quite low level functionality which is purely there >> to implement other synchronization features like Mutex, Monitor etc. >> >> - Although they might not be deprecated when we have a Ruby version >> that supports native threads the effect of using this single process >> wide lock will be even more dramatic, because there will be even >> more unused resources when the lock is held - especially in >> multiprocessor environments. > > Agreed, with regard to multiprocessor environments. With ruby's > current implementation, using Thread.exclusive _where appropriate_ > seems perfectly reasonable to me. Grep ruby's standard library, > you'll see several instances of its use. > > For instance drb/drb.rb DRbServer#initialize does the following: > > Thread.exclusive do > DRb.primary_server = self unless DRb.primary_server > end > > Yes, that could have been done with a Mutex, but why? Calling > Mutex#synchronize (which in turn calls Mutex#lock and Mutex#unlock) > involves considerably more code executed inside Thread.critical blocks > than that one-liner above. > > So if the argument is that Thread.critical is prohibitively costly, > one had better bear that in mind when calling any methods on Mutex. > > In the current implementation, each call to Mutex#synchronize > involves around ten or so lines of ruby executed in at least > two separate Thread.critical blocks (one of which is in a loop.) > > I agree that the relative costs of all these operations may change > when we get to YARV + native threads + fine-grained locking that > allows multiple ruby threads simultaneously executing on multiple > processors. I wouldn't be surprised if Ruby's current thread.rb > implementation had to be rewritten for that new system. I expect exactly that to happen - even more so, these classes are likely candidates for an implementation in the runtime system (similarly to Java's approach). > But in any case, with ruby's current green threads, Thread.exclusive > is about as efficient as you can get, for simple cases like the > DRb one shown above. All it does is extend the current thread's > quantum, effectively, for a brief period of time. There's no > waiting involved. I still don't like this approach even if the std lib does it. In an application you'll usually want more fine grained locks than process wide locks. IMHO it's not only a question of efficiency but also of design. I prefer to start with the cleaner design and only change to Thread.exclusive if there is a real need for this. I guess you know the quote about premature optimization... Of course you can view the usage of several lower grained locks vs. Thread.exclusive as an optimization, too (increases throughput). :-)) Although we differ on this one I guess we've given good arguments for both approaches so people can pick whatever they feel more comfortable with. Kind regards robert PS: Since I do Java for a living it's MT approach might have influenced me, there's simply no such thing as an application wide thread exclusive execution.