操纵另一个线程正在使用的数据集

时间:2013-07-15 14:29:37

标签: ruby multithreading concurrency

我有sinatra设置,听取github repo的提交。我当前设置的系统,监听帖子,然后将有效负载推送到有效负载阵列。然后我打电话给

@@payloads.each do .... whatever

如果有多个帖子来自github,即人们在@@payloads.each运行时推送更多提交,会发生什么?如果有一个有效载荷,那么另一个有效载荷被驱动,payloads.each呼叫圈是否又一次?或者是否进行了设置,以便在呼叫完成后.each呼叫经过的有效负载数量一成不变?

2 个答案:

答案 0 :(得分:1)

作为一个FYI,除非您同步访问,否则您可能会遇到读/写同一个数组的问题。看看Ruby的内置Queue类。它是Thread的一部分。

您可以拥有多个不会发生冲突的生产者/消费者。这是文档所说的内容:

  

此类提供了一种同步线程之间通信的方法。

     

示例:

    require 'thread'

    queue = Queue.new

    producer = Thread.new do
      5.times do |i|
        sleep rand(i) # simulate expense
        queue << i
        puts "#{i} produced"
      end
    end

    consumer = Thread.new do
      5.times do |i|
        value = queue.pop
        sleep rand(i/2) # simulate expense
        puts "consumed #{value}"
      end
    end

    consumer.join

至于使用each循环数组,我认为你应该使用语法:

loop do
  break if @@payloads.empty?
end

each意味着要迭代的有限元素集。描述说:

  

为self ....中的每个元素调用给定的块一次。

在其他语言中,您无法更改正在迭代的容器,因为元素的数量是在循环开始时设置的;尝试更改容器会引发错误。依靠each允许你这样做可能会导致期望你会看到其他语言的行为;在我看来,你依赖于副作用或侧门,这不是一个好习惯。

loop并不意味着因为它是一个简单的循环,你必须有条件地摆脱使用自己的逻辑。以下是loop的示例:

loop do
  print "Input: "
  line = gets
  break if !line or line =~ /^qQ/
  # ...
end

没有假设元素的数量,它完全是开放式的。并且,它很容易爆发,因为Queue具有必要的empty?方法。

这是我的0.02美元以及我是如何做到的。

查看页面右侧的“相关”主题以获得更多想法。

答案 1 :(得分:1)

只要@@payloads是标准的ruby数组,推送的有效负载就应该包含在#each次迭代中。

当一个线程迭代一个数组,另一个线程追加到同一个数组时,迭代线程将包含附加项。

Take a look at this gist有一个简单的程序来演示这种行为。一个线程迭代,而另一个线程添加到数组。由于ruby中线程调度的性质,每次结果可能都不同。