Is there any practical difference between Ruby pre-1.9 and Ruby 1.9 threads?
I'm trying to understand the difference between Ruby threads pre-1.9 and 1.9 (in the standard MRI implementation), but it seems that in terms of the benefits you can achieve with them, they're practically the same. Is this correct?
From my limited understanding:
- Pre-1.9 threads are "green threads", which means that they're managed by the Ruby interpreter, not the OS. One consequence of this is that you never achieve true concurrency, since you never have multiple threads running at the same time (even if you're on a multicore/multiprocessor system). (However, you can get the appearance of concurrency, if execution switches between different threads, e.g., if som开发者_运维百科e program runs while another is waiting on I/O.)
- 1.9 threads are native threads, which means that they are indeed managed by the OS. If there were no global interpreter lock, this would allow Ruby to run multiple threads at the same time (on a multicore/multiprocessor system). But Ruby does have a global interpreter lock, which means that only one thread can ever be running, so again you don't get true concurrency. (But you can still get the appearance of concurrency if execution switches between different threads.)
Is this correct, or am I missing something? What are the benefits of 1.9 threads vs. pre-1.9 threads (in MRI)?
I feel kind of silly offering this as an answer, but your description matches my understanding of the situation perfectly.
If we are right, I should add that it does make sense to evolve the language this way.
Keep in mind that a main point of functional programming, the Actor Model, and other shared-memory-alternative parallel models is to fix the extreme difficulty of developing a parallel shared-memory application. ("Threads considered harmful.")
So it would have been expecting way too much for Ruby to go from nothing-parallel to everything-parallel.
The current approach seems to be to set up the mechanism but to keep the giant lock. I presume that in the future, individually debugged and tested functional areas will be allowed to execute in parallel as they receive fine-grain locks and concurrency testing.
Your analysis is perfectly correct, ruby 1.9 now uses native thread but since there is the Global Interpreter Lock you really get nothing from it in your ruby code.
There is already some work to change this in other implementations:
JRuby already removed the GIL (I am not sure if there was once a GIL to begin with) but the implementation is not 100% percent compatible with MRI mostly because of native gems if you use them (JRuby does not allow C extensions)
Rubinius 2.0 will get rid of the GIL and work on this should be nearing completion now: a prerelease version is already being tested and works quite well already.
Edit: ruby 1.9 however added Fiber which can be a nice alternative in specific cases, they are like thread but you are the one scheduling them.
Edit2: rubinius news on 2.0 developer release: http://rubini.us/2011/06/07/inside-rubinius-20-preview/
Under 1.9, one thread can be doing I/O, while another thread is doing CPU work.
I’ve heard a common misperception that Ruby inherently “blocks” when doing disk IO or making database queries. In reality, Ruby switches to another thread whenever it needs to block for IO. In other words, if a thread needs to wait, but isn’t using any CPU, Ruby’s built-in methods allow another waiting thread to use the CPU while the original thread waits.
Which isn't much help for me, as I'm not I/O bound, but it may be good news for you.
精彩评论