Зависит от реализации:
- МРТ не имеет, ЯРВ ближе.
- JRuby и MacRuby имеют.
Руби имеет замыканий как Blocks
, lambdas
и Procs
. Чтобы воспользоваться всеми преимуществами замыканий и нескольких ядер в JRuby, пригодятся исполнители Java ; для MacRuby мне нравятся очереди GCD .
Обратите внимание, что возможность создавать реальных потоков «уровня ОС» не означает, что вы можете использовать несколько ядер ЦП для параллельной обработки. Посмотрите на примеры ниже.
Это вывод простой программы на Ruby, которая использует 3 потока с использованием Ruby 2.1.0:
(jalcazar@mac ~)$ ps -M 69877
USER PID TT %CPU STAT PRI STIME UTIME COMMAND
jalcazar 69877 s002 0.0 S 31T 0:00.01 0:00.04 /Users/jalcazar/.rvm/rubies/ruby-2.1.0/bin/ruby threads.rb
69877 0.0 S 31T 0:00.01 0:00.00
69877 33.4 S 31T 0:00.01 0:08.73
69877 43.1 S 31T 0:00.01 0:08.73
69877 22.8 R 31T 0:00.01 0:08.65
Как вы можете видеть здесь, существует четыре потока ОС, однако работает только один с состоянием R
. Это связано с ограничением реализации потоков в Ruby.
Та же программа, теперь с JRuby. Вы можете видеть три потока с состоянием R
, что означает, что они работают параллельно.
(jalcazar@mac ~)$ ps -M 72286
USER PID TT %CPU STAT PRI STIME UTIME COMMAND
jalcazar 72286 s002 0.0 S 31T 0:00.01 0:00.01 /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java -Djdk.home= -Djruby.home=/Users/jalcazar/.rvm/rubies/jruby-1.7.10 -Djruby.script=jruby -Djruby.shell=/bin/sh -Djffi.boot.library.path=/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jni:/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jni/Darwin -Xss2048k -Dsun.java.command=org.jruby.Main -cp -Xbootclasspath/a:/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jruby.jar -Xmx1924M -XX:PermSize=992m -Dfile.encoding=UTF-8 org/jruby/Main threads.rb
72286 0.0 S 31T 0:00.00 0:00.00
72286 0.0 S 33T 0:00.00 0:00.00
72286 0.0 S 31T 0:00.09 0:02.34
72286 7.9 S 31T 0:00.15 0:04.63
72286 0.0 S 31T 0:00.00 0:00.00
72286 0.0 S 31T 0:00.00 0:00.00
72286 0.0 S 31T 0:00.00 0:00.00
72286 0.0 S 31T 0:00.04 0:01.68
72286 0.0 S 31T 0:00.03 0:01.54
72286 0.0 S 31T 0:00.00 0:00.00
72286 0.0 S 31T 0:00.01 0:00.01
72286 0.0 S 31T 0:00.00 0:00.01
72286 0.0 S 31T 0:00.00 0:00.03
72286 74.2 R 31T 0:09.21 0:37.73
72286 72.4 R 31T 0:09.24 0:37.71
72286 74.7 R 31T 0:09.24 0:37.80
Та же самая программа, теперь с MacRuby. Есть также три потока, работающих параллельно. Это связано с тем, что потоки MacRuby являются потоками POSIX ( настоящие потоки "уровня ОС" ), а нет GVL
(jalcazar@mac ~)$ ps -M 38293
USER PID TT %CPU STAT PRI STIME UTIME COMMAND
jalcazar 38293 s002 0.0 R 0T 0:00.02 0:00.10 /Users/jalcazar/.rvm/rubies/macruby-0.12/usr/bin/macruby threads.rb
38293 0.0 S 33T 0:00.00 0:00.00
38293 100.0 R 31T 0:00.04 0:21.92
38293 100.0 R 31T 0:00.04 0:21.95
38293 100.0 R 31T 0:00.04 0:21.99
Еще раз, та же программа, но теперь со старой доброй МРТ. В связи с тем, что в этой реализации используются зеленые потоки, отображается только один поток
(jalcazar@mac ~)$ ps -M 70032
USER PID TT %CPU STAT PRI STIME UTIME COMMAND
jalcazar 70032 s002 100.0 R 31T 0:00.08 0:26.62 /Users/jalcazar/.rvm/rubies/ruby-1.8.7-p374/bin/ruby threads.rb
Если вас интересует многопоточность в Ruby, вы можете найти мой отчет Отладка параллельных программ с использованием обработчиков вил интересно.
Для более общего обзора внутренних компонентов Ruby Ruby Under the Microscope - хорошее чтение.
Кроме того, потоки Ruby и глобальная блокировка интерпретатора в C в Omniref объясняют в исходном коде, почему потоки Ruby не работают параллельно.