Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby线程和变量_Ruby_Multithreading_Thread Safety - Fatal编程技术网

Ruby线程和变量

Ruby线程和变量,ruby,multithreading,thread-safety,Ruby,Multithreading,Thread Safety,为什么结果不是从1到10,而是10秒 require 'thread' def run(i) puts i end while true for i in 0..10 Thread.new{ run(i)} end sleep(100) end 结果: 10 10 10 10 10 10 10 10 10 10 10 0 1 2 3 4 5 6 7 8 9 10 为什么循环?我正在运行while loop,因为以后我想一直遍历DB表,并回显从DB检索到的任何记录

为什么结果不是从1到10,而是10秒

require 'thread'

def run(i)
  puts i
end

while true
  for i in 0..10
    Thread.new{ run(i)}
  end
  sleep(100)
end
结果:

10
10
10
10
10
10
10
10
10
10
10
0
1
2
3
4
5
6
7
8
9
10

为什么循环?我正在运行while loop,因为以后我想一直遍历DB表,并回显从DB检索到的任何记录。

问题是您创建了11个线程,它们都试图访问由程序主线程定义的相同变量
I
。避免这种情况的一个技巧是在方法内部调用
Thread.new
;那么线程可以访问的变量
i
就是传递给方法的特定
i
,它不会与其他线程共享。这充分利用了

结果:

10
10
10
10
10
10
10
10
10
10
10
0
1
2
3
4
5
6
7
8
9
10

(我添加了
sleep
,只是为了保证线程以数字顺序运行,这样我们就可以有整洁的输出,但您可以将其取出,并且仍然有一个有效的程序,其中每个线程都有正确的参数。)

@DavidGrayson是正确的

您可以在
for loop
中看到一个副作用。在您的情况下,
i
变量范围是整个文件。而您只希望在
for循环
中有一个块作为作用域。实际上,这在惯用Ruby中是错误的方法。Ruby为这个任务提供迭代器

(1..10).each do |i|
   Thread.new{ run(i)}
end

在这种情况下,变量
i
的作用域将被隔离在块作用域中,这意味着对于每次迭代,您将获得新的局部变量
i
传递给
线程的块。新的
实际上可能在将来的某个点开始,到那时
i
的值可能已经改变。在您的例子中,在所有线程实际运行之前,它们都增加到
10

要解决此问题,除块外,使用接受参数的形式:

require 'thread'

def run(i)
  puts i
end

while true
  for i in 0..10
    Thread.new(i) { |j| run(j) }
  end
  sleep(100)
end

这将在调用
new
时将块变量
j
设置为
i
的值。

实际上,我在我的机器上运行了你的代码,得到了一些
3
s和一些
10
s。@DavidGrayson你在这里会得到什么是不可预测的。您不能保证线程上下文切换。所以你可以根据月亮的相位得到很多不同的结果。太棒了!那么现在第二部分:)