From: Tony Arcieri Date: 2011-10-20T02:00:33+09:00 Subject: Re: Ruby and threading --0015174c0f8c0487c204afa9c77f Content-Type: text/plain; charset=ISO-8859-1 On Wed, Oct 19, 2011 at 8:32 AM, Josh Cheek wrote: > When it's in a lib you don't control, it's useful. A wrapped C lib is > probably the best example, but even if its in someone else's gem, it's > relevant. Debugging libs takes a lot of time and effort, especially for > something nondeterministic that may or may not reproduce itself. > > Rbx / JRuby / MacRuby will need resources to educate their users about how > to write safe code, and may also need to maintain a list of safe gems. > The GIL doesn't eliminate the importance of writing thread safe code, it just masks the symptoms of unsafe code in certain cases. It's not some magical panacea. Users of Ruby 1.9 who use threads need to be just as vigilant about the thread safety of their code. Otherwise their programs are working by accident, such as your "needs_gil.rb". The fact that program works is an implementation detail of the GIL on 1.9.2, it's not as if Matz has said "all operations on arrays should be automatically thread synchronized", which is still possible on VMs without a GIL (although I'm surprised the above doesn't trigger a ConcurrentModificationException on JRuby) As an example of thread safety problems even with a GIL, try running the following on 1.9.2: -- snip -- require 'thread' numbers = [0] threads = [] #lock = Mutex.new 100.times do threads << Thread.new do size = nil begin #lock.synchronize do value = rand(101) if value == numbers.last + 1 sleep 0.01 numbers << value end size = numbers.size #end end while size < 100 end end threads.each(&:join) p numbers -- snip -- It's a bit contrived and goofy, but whatever. The output should look like this: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100] However if you run the above code with the lock commented out, even on 1.9.2 you'll get something like this instead: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] Broken, thread-unsafe code is broken, thread-unsafe code. It doesn't matter if it magically happens to work by accident in 1.9.2. It's still broken. The GIL doesn't mean you can avoid teaching users of threads about thread safety, or that you don't need to maintain a list of safe gems ( railsplugins.org is trying to do this, BTW, although I wish it were built into RubyGems). You still need to do these things on 1.9.2. The difference is the GIL will *mask* certain thread safety bugs, but not all of them. "I don't need to worry about thread safety because the GIL will take care of it for me" is definitely the wrong attitude. -- Tony Arcieri --0015174c0f8c0487c204afa9c77f--