与Fibers的简单并行性?

时间:2016-06-01 13:18:56

标签: ruby fibers

我正在尝试用两根光纤验证基本的良品率/恢复模式。但是,收益/恢复机制似乎不起作用。我尝试了一些变化,但找不到我的错误。

预期的事件顺序:

  1. 启动线程(时间0)
  2. 等到第一次返回(时间+ 2秒)
  3. 等到第二次返回(时间+2秒)
  4. 完成(时间> + 3秒)
  5. 尝试#1

    #!/usr/bin/env ruby
    
    require 'fiber'
    
    f1 = Fiber.new do
        puts "Fiber1 starting @ #{Time.new}."
        fib1 = Fiber.current
        Fiber.yield
        sleep 2
        puts "Fiber1 done @ #{Time.new}."
        fib1.resume(1)
    end
    f2 = Fiber.new do
        puts "Fiber2 starting @ #{Time.new}."
        fib2 = Fiber.current
        Fiber.yield
        sleep 2
        puts "Fiber2 done @ #{Time.new}."
        fib2.resume(2)
    end
    
    puts "Waiting @ #{Time.new}."
    r1 = f1.resume
    puts "f1 back @ #{Time.new} - #{r1}."
    r2 = f2.resume
    puts "f2 back @ #{Time.new} - #{r2}."
    
    sleep 1
    puts "Done @ #{Time.now}."
    

    这导致:

    Waiting @ 2016-06-01 06:15:52 -0700.
    Fiber1 starting @ 2016-06-01 06:15:52 -0700.
    f1 back @ 2016-06-01 06:15:52 -0700 - .
    Fiber2 starting @ 2016-06-01 06:15:52 -0700.
    f2 back @ 2016-06-01 06:15:52 -0700 - .
    Done @ 2016-06-01 06:15:53 -0700.
    

    添加第二个resume会导致FiberError。

    尝试#2

    #!/usr/bin/env ruby
    
    require 'fiber'
    
    f1 = Fiber.new do
        puts "Fiber1 starting @ #{Time.new}."
        Fiber.yield
        sleep 2
        puts "Fiber1 done @ #{Time.new}."
        1
    end
    f2 = Fiber.new do
        puts "Fiber2 starting @ #{Time.new}."
        Fiber.yield
        sleep 2
        puts "Fiber2 done @ #{Time.new}."
        2
    end
    
    puts "Waiting @ #{Time.new}."
    r1 = f1.resume
    puts "f1 back @ #{Time.new} - #{r1}."
    r2 = f2.resume
    puts "f2 back @ #{Time.new} - #{r2}."
    
    sleep 1
    puts "Done @ #{Time.now}."
    

    这导致:

    Waiting @ 2016-06-01 10:53:17 -0700.
    Fiber1 starting @ 2016-06-01 10:53:17 -0700.
    f1 back @ 2016-06-01 10:53:17 -0700 - .
    Fiber2 starting @ 2016-06-01 10:53:17 -0700.
    f2 back @ 2016-06-01 10:53:17 -0700 - .
    Done @ 2016-06-01 10:53:18 -0700.
    

    在这两种情况下,开始/结束时间都相同,结果不会返回。

1 个答案:

答案 0 :(得分:1)

光纤本身不会让你实现并行性,至少不使用某种回调机制,比如eventmachine framework。

您所写的只是尝试在代码块之间交错同步执行。你没有得到预期序列的原因是因为当你模拟开球时,你从未在完成之后恢复光纤。

您可能会发现以下帖子很有用,特别是最后的示例:
http://schmurfy.github.io/2011/09/25/on_fibers_and_threads.html

另一个例子显示纤维相互转移控制:
https://gist.github.com/aprescott/971008

这应该会给你预期的结果:

#!/usr/bin/env ruby

require 'fiber'

f1 = Fiber.new do
    puts "Fiber1 starting @ #{Time.new}."
    Fiber.yield
    sleep 2
    puts "Fiber1 done @ #{Time.new}."
    1
end
f2 = Fiber.new do
    puts "Fiber2 starting @ #{Time.new}."
    Fiber.yield
    sleep 2
    puts "Fiber2 done @ #{Time.new}."
    2
end

puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."

# Resume right after the yield in the fiber block and 
# execute until it encounters another yield or the block ends.
puts "Resuming f1"
f1.resume 
puts "Resuming f2"
f2.resume

sleep 1
puts "Done @ #{Time.now}."

输出:

Waiting @ 2016-06-05 00:35:29 -0700.
Fiber1 starting @ 2016-06-05 00:35:29 -0700.
f1 back @ 2016-06-05 00:35:29 -0700 - .
Fiber2 starting @ 2016-06-05 00:35:29 -0700.
f2 back @ 2016-06-05 00:35:29 -0700 - .
Resuming f1
Fiber1 done @ 2016-06-05 00:35:31 -0700.
Resuming f2
Fiber2 done @ 2016-06-05 00:35:33 -0700.
Done @ 2016-06-05 00:35:34 -0700.