ruby 线程#run和线程#wakeup之间的区别?

zlwx9yxi  于 2023-03-12  发布在  Ruby
关注(0)|答案(2)|浏览(122)

在Ruby中,Thread#run和Thread#wakup有什么区别?
RDoc指定 scheduler 不随Thread#wakeup调用,但这意味着什么?什么时候使用 wakeuprun 的示例?谢谢。

编辑:

我看到Thread#wakup使线程变得可运行,但是如果在执行Thread#run之前它不会执行(无论如何都会唤醒线程),那么它有什么用呢?
有人能提供一个 wakeup 做一些有意义的事情的例子吗?出于好奇心=)

py49o6xq

py49o6xq1#

下面是一个示例来说明它的含义(代码示例来自here):

线程唤醒

thread = Thread.new do 
  Thread.stop
  puts "Inside the thread block"
end

$ thread
=> #<Thread:0x100394008 sleep>

上面的输出表明新创建的线程由于stop命令而处于休眠状态。

$ thread.wakeup
=> #<Thread:0x100394008 run>

此输出指示线程不再休眠,可以运行。

$ thread.run
Inside the thread block
=> #<Thread:0x1005d9930 sleep>

现在线程继续执行并打印出字符串。

$ thread.run
ThreadError: killed thread

线程运行

thread = Thread.new do 
  Thread.stop
  puts "Inside the thread block"
end

$ thread
=> #<Thread:0x100394008 sleep> 

$ thread.run
Inside the thread block
=> #<Thread:0x1005d9930 sleep>

线程不仅唤醒,而且继续执行并打印出字符串。

$ thread.run
ThreadError: killed thread
yfwxisqw

yfwxisqw2#

runwakeup之间的区别正是文档中所说的,尽管文档是关于Ruby类库的,并且没有提到MRI/YARV实现的细节,这是有意义的,因为还有其他实现,如JRuby,具有“真实的的”线程。
wakeup使线程可调度(aka runnable),但不立即运行它。run也使线程可调度,但立即运行它。
在MRI/YARV上,最初似乎wakeup什么也不做,但这是实现的特性。MRI/YARV有一个GVL,它一次只允许一个线程在Ruby VM中运行。线程不会被抢占,而是一直运行,直到它们放弃控制权(Thread.passKernel.sleep等)或进入I/O等待,在这两种情况下,线程调度程序都会恢复当前可运行的线程之一。因此,如果您调用wakeup,然后调用Thread.pass或导致I/O wait(例如gets),您将看到另一个线程正在执行。
因此,在MRI/YARV上,如果有2个线程,Thread.run实际上等于Thread.wakeup + Thread.pass。如果有更多的Thread.pass,则不一定启动被唤醒的线程,但会启动调度程序认为下一个应该运行的线程。这使得run方法成为必要,因为这是唤醒线程并使其运行的方法。就在此时此地,而不是把它留给调度程序(这对所有实现都是正确的,即使是具有“真实的”线程的实现)。

相关问题