17

在线程外部定义的局部变量似乎从内部可见,因此以下两种用法Thread.new似乎是相同的:

a = :foo
Thread.new{puts a} # => :foo
Thread.new(a){|a| puts a} # => :foo

文档给出了示例:

arr = []
a, b, c = 1, 2, 3
Thread.new(a,b,c){|d, e, f| arr << d << e << f}.join
arr #=> [1, 2, 3]

但由于a, b,c从创建的线程内部可见,这也应该与以下内容相同:

arr = []
a, b, c = 1, 2, 3
Thread.new{d, e, f = a, b, c; arr << d << e << f}.join
arr #=> [1, 2, 3]

有什么区别吗?什么时候需要将局部变量作为参数传递给Thread.new?

4

2 回答 2

24

当您将变量传递给这样的线程时,线程会生成变量的本地副本并使用它,因此对其进行修改不会影响您传入的线程之外的变量

a = "foo"
Thread.new{ a = "new"}
p a # => "new"
Thread.new(a){|d| d = "old"} 
p a # => "new"
p d # => undefined
于 2013-05-25T05:53:09.603 回答
1

我想我遇到了实际问题。使用这样的代码:

    sock = Socket.unix_server_socket(SOCK)
    sock.listen 10
    while conn = sock.accept do
        io, address = conn
        STDERR.puts "#{io.fileno}: Accepted connection from '#{address}'"
        Thread.new{ serve io }
    end

它在接受很少的连接时似乎有效。当一个接一个地快速接受连接时,问题就来了。对局部变量 io 的更新将反映在多个并发线程中,除非作为参数传递给 Thread.new

于 2020-01-10T02:01:56.050 回答