当前位置:  开发笔记 > 编程语言 > 正文

ruby有真正的多线程吗?

如何解决《ruby有真正的多线程吗?》经验,为你挑选了3个好方法。

我知道使用绿色线程的ruby的"合作" 线程.如何在我的应用程序中创建真正的"操作系统级"线程,以便使用多个cpu内核进行处理?



1> Jörg W Mitta..:

更新了Jörg的2011年9月评论

你似乎混淆了两个非常这里不同的东西:Ruby编程语言和一个具体实施Ruby编程语言的特定线程模型.目前有大约11种不同的Ruby编程语言实现,具有非常不同且独特的线程模型.

(不幸的是,这11个实现中只有两个实际上已准备好用于生产,但到年底这个数字可能会达到四个或五个.)(更新:它现在是5:MRI,JRuby,YARV(解释器)对于Ruby 1.9),Rubinius和IronRuby).

    第一个实现实际上没有名称,这使得引用它非常尴尬,并且真的很烦人和令人困惑.它通常被称为"Ruby",它比没有名称更令人讨厌和混乱,因为它导致Ruby编程语言的特性和特定的Ruby实现之间的无休止的混淆.

    它有时也被称为"MRI"(用于"Matz的Ruby实现"),CRuby或MatzRuby.

    MRI在其解释器中将Ruby Threads实现为绿色线程.不幸的是,它不允许并行调度这些线程,它们一次只能运行一个线程.

    但是,任何数量的C线程(POSIX线程等)都可以与Ruby线程并行运行,因此创建自己的线程的外部C库或MRI C Extensions仍然可以并行运行.

    第二个实现是YARV("又一个Ruby VM"的缩写).YARV将Ruby Threads实现为POSIX或Windows NT线程,但是,它使用全局解释器锁(GIL)来确保一次只能实际调度一个Ruby线程.

    MRI一样,C线程实际上到Ruby线程并行运行.

    将来,有可能GIL 可能被分解为更细粒度的锁,从而允许越来越多的代码实际并行运行,但是这个目前还远,它甚至还没有计划好.

    JRuby将 Ruby Threads实现为Native Threads,其中"Native Threads"在JVM的情况下显然意味着"JVM Threads".JRuby没有对它们施加额外的锁定.因此,这些线程是否可以实际并行运行取决于JVM:一些JVM将JVM线程实现为OS线程,一些实现为绿色线程.(自JDK 1.3起,Sun/Oracle的主流JVM专门使​​用OS线程)

    XRuby还将Ruby Threads实现为JVM线程.更新:XRuby死了.

    IronRuby将 Ruby Threads实现为Native Threads,其中CLR的"Native Threads"显然意味着"CLR Threads".IronRuby不对它们施加额外的锁定,因此,只要您的CLR支持它,它们就应该并行运行.

    Ruby.NET还将Ruby Threads实现为CLR线程.更新: Ruby.NET已经死了.

    Rubinius 在其虚拟机中将Ruby Threads实现为绿色线程.更确切地说:Rubinius VM导出一个非常轻量级,非常灵活的并发/并行/非本地控制流构造,称为" 任务 ",以及所有其他并发构造(本讨论中的线程,还有Continuations,Actors和其他东西) )使用Tasks在纯Ruby中实现.

    Rubinius不能(当前)并行调度线程,但是,添加这并不是一个问题:Rubinius已经可以在一个Rubinius进程中并行运行多个POSIX线程中的多个VM实例.由于Threads实际上是在Ruby中实现的,因此它们可以像任何其他Ruby对象一样被序列化并发送到不同POSIX线程中的不同VM.(这与BEAM Erlang VM用于SMP并发的模型相同.它已经为Rubinius Actors实现.)

    更新:在这个答案中关于Rubinius的信息是关于Shotgun VM,它不再存在."新"C++ VM不使用跨多个VM调度的绿色线程(即Erlang/BEAM样式),它使用具有多个本机OS线程模型的更传统的单个VM,就像CLR,Mono所采用的那样. ,几乎每个JVM.

    MacRuby最初是在Objective-C Runtime和CoreFoundation以及Cocoa框架之上的YARV端口.它现在与YARV显着不同,但AFAIK目前仍然与YARV共享相同的线程模型. 更新: MacRuby依赖于苹果垃圾收集器,它被声明为已弃用,将在MacOSX的更高版本中删除,MacRuby是不死的.

    Cardinal是Parrot虚拟机的Ruby实现.它还没有实现线程,但是,当它执行时,它可能会将它们实现为Parrot线程.更新:红衣主教似乎非常不活跃/死亡.

    MagLev是GemStone/S Smalltalk VM的Ruby实现.我没有掌握GemStone/S使用的线程模型,MagLev使用的线程模型,甚至线程甚至尚未实现(可能不是).

    HotRuby是不是它自己的完整的Ruby实现.它是JavaScript中YARV字节码VM的实现.HotRuby不支持线程(但是?),当它执行时,它们将无法并行运行,因为JavaScript不支持真正的并行性.但是,有一个ActionScript版本的HotRuby,ActionScript实际上可能支持并行性.更新:HotRuby已经死了.

不幸的是,这11个Ruby实现中只有两个实际上是生产就绪的:MRI和JRuby.

所以,如果你想要真正的并行线程,JRuby目前是你唯一的选择 - 而不是那个糟糕的:JRuby实际上比MRI快,可以说更稳定.

否则,"经典"Ruby解决方案是使用进程而不是线程来实现并行性.Ruby Core Library包含带有 方法的Process模块,这使得很容易分离出另一个Ruby进程.此外,Ruby标准库包含 分布式Ruby(dRuby/dRb)库,它允许Ruby代码轻松地分布在多个进程中,不仅在同一台机器上,而且在整个网络中.Process.fork



2> Josh Moore..:

Ruby 1.8只有绿色线程,没有办法创建一个真正的"操作系统级"线程.但是,ruby 1.9将有一个名为fiber的新功能,它将允许您创建实际的操作系统级线程.不幸的是,Ruby 1.9仍然处于测试阶段,计划在几个月后保持稳定.

另一种选择是使用JRuby.JRuby将线程实现为OS级别的theads,其中没有"绿色线程".JRuby的最新版本是1.1.4,相当于Ruby 1.8


Ruby 1.8只有绿色线程是错误的,Ruby 1.8的几个实现都有本机线程:JRuby,XRuby,Ruby.NET和IronRuby.光纤不允许创建本机线程,它们比线程更轻量级*.它们实际上是半协同程序,即它们是合作的.
我认为从Josh的回答中可以明显看出,当他说Ruby 1.8时,他认为Ruby 1.8是运行时,即MRI,而不是Ruby 1.8.

3> user454322..:

这取决于实施:

RMI没有,YARV更接近.

JRuby和MacRuby有.




Ruby有倒闭的Blocks,lambdasProcs.为了充分利用JRuby中的闭包和多核,Java的执行器就派上用场了; 对于MacRuby我喜欢GCD的队列.

请注意,能够创建真正的"OS级"线​​程并不意味着您可以使用多个cpu内核进行并行处理.请看下面的例子.

这是使用Ruby 2.1.0 使用3个线程的简单Ruby程序的输出:

(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 

正如您在此处看到的,有四个OS线程,但只有一个状态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线程(真正的"OS级"线​​程)并且没有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 


再次,相同的程序,但现在与良好的旧RMI.由于此实现使用绿色线程,因此只显示一个线程

(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多线程感兴趣,可能会发现我的报告使用fork处理程序调试并行程序很有趣.
有关Ruby内部的更一般概述Ruby Under a Microscope是一本很好的读物.
此外,Ruby Threads和 Omniref 中的C语言全局解释器锁在源代码中解释了为什么Ruby线程不能并行运行.

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有