Ruby线程:对象的方法和实例

Ruby线程:对象的方法和实例,ruby,multithreading,Ruby,Multithreading,考虑下面的代码片段。在其中,我定义了一个名为doit的方法,该方法随后从两个不同的线程调用 与我预期的相反,方法中的t.object\u id不断返回两个不同的id,就好像每个线程对方法的调用都收到了内存中自己的空间 我所期望的是,在进入该方法的第二个线程上,它将替换先前定义的散列,从而在剩余时间打印相同的对象ID。换句话说,我认为会有一个散列实例 可以说,这表明该方法的第一个条目中的循环会阻止任何后续访问,但情况显然并非如此 那么,如何处理这些方法呢?来自单独线程的每个调用是否在内存中接收自己

考虑下面的代码片段。在其中,我定义了一个名为
doit
的方法,该方法随后从两个不同的线程调用

与我预期的相反,方法中的
t.object\u id
不断返回两个不同的id,就好像每个线程对方法的调用都收到了内存中自己的空间

我所期望的是,在进入该方法的第二个线程上,它将替换先前定义的散列,从而在剩余时间打印相同的对象ID。换句话说,我认为会有一个散列实例

可以说,这表明该方法的第一个条目中的循环会阻止任何后续访问,但情况显然并非如此

那么,如何处理这些方法呢?来自单独线程的每个调用是否在内存中接收自己的副本?正确的理解方法是什么

def doit
    t = Hash.new
    puts t.object_id
    loop do
      sleep 1
      puts t.object_id
    end
end

t1 = Thread.new { doit }
t2 = Thread.new { doit }

t1.join
t2.join
举例来说,这是输出:

21329316
21327684
21329316
21327684
21329316
21327684
21327684
21329316
21327684
21329316
21327684
21329316

t
doit
的局部变量,它仅在方法的范围内声明。每次执行都会收到自己的
t

如果要共享
t
,请将其声明为实例成员
@t

def doit
    @t = Hash.new
    puts @t.object_id
    loop do
      sleep 1
      puts @t.object_id
    end
end

t1 = Thread.new { doit }
t2 = Thread.new { doit }

t1.join
t2.join
现在,您的输出将如下所示:

15223760
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580

t
doit
的局部变量,它仅在方法的范围内声明。每次执行都会收到自己的
t

如果要共享
t
,请将其声明为实例成员
@t

def doit
    @t = Hash.new
    puts @t.object_id
    loop do
      sleep 1
      puts @t.object_id
    end
end

t1 = Thread.new { doit }
t2 = Thread.new { doit }

t1.join
t2.join
现在,您的输出将如下所示:

15223760
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580

t
doit
的局部变量,它仅在方法的范围内声明。每次执行都会收到自己的
t

如果要共享
t
,请将其声明为实例成员
@t

def doit
    @t = Hash.new
    puts @t.object_id
    loop do
      sleep 1
      puts @t.object_id
    end
end

t1 = Thread.new { doit }
t2 = Thread.new { doit }

t1.join
t2.join
现在,您的输出将如下所示:

15223760
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580

t
doit
的局部变量,它仅在方法的范围内声明。每次执行都会收到自己的
t

如果要共享
t
,请将其声明为实例成员
@t

def doit
    @t = Hash.new
    puts @t.object_id
    loop do
      sleep 1
      puts @t.object_id
    end
end

t1 = Thread.new { doit }
t2 = Thread.new { doit }

t1.join
t2.join
现在,您的输出将如下所示:

15223760
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580
15223580

线程与此无关
t
是在每次调用
doit
时初始化的局部变量,因此每次调用都会得到自己的
t
。请注意,删除线程会得到相同的结果,尽管不是交错的:

def doit
  t = Hash.new
  t.object_id
end

doit #=> 21329316
doit #=> 21327684

线程与此无关
t
是在每次调用
doit
时初始化的局部变量,因此每次调用都会得到自己的
t
。请注意,删除线程会得到相同的结果,尽管不是交错的:

def doit
  t = Hash.new
  t.object_id
end

doit #=> 21329316
doit #=> 21327684

线程与此无关
t
是在每次调用
doit
时初始化的局部变量,因此每次调用都会得到自己的
t
。请注意,删除线程会得到相同的结果,尽管不是交错的:

def doit
  t = Hash.new
  t.object_id
end

doit #=> 21329316
doit #=> 21327684

线程与此无关
t
是在每次调用
doit
时初始化的局部变量,因此每次调用都会得到自己的
t
。请注意,删除线程会得到相同的结果,尽管不是交错的:

def doit
  t = Hash.new
  t.object_id
end

doit #=> 21329316
doit #=> 21327684

结果正如预期的那样,我认为doit的这两个调用在堆栈中有自己的内存空间。如果希望两个线程在一个对象上运行,请尝试将参数传递给该方法。就像doit(t)@GingerJim一样,这是行不通的,因为参数引用被复制到本地成员-
t=Hash。在函数的另一次调用中,new
不会改变
t
。结果正如预期的那样,我认为doit的这两次调用在堆栈中有自己的内存空间。如果希望两个线程在一个对象上运行,请尝试将参数传递给该方法。就像doit(t)@GingerJim一样,这是行不通的,因为参数引用被复制到本地成员-
t=Hash。在函数的另一次调用中,new
不会改变
t
。结果正如预期的那样,我认为doit的这两次调用在堆栈中有自己的内存空间。如果希望两个线程在一个对象上运行,请尝试将参数传递给该方法。就像doit(t)@GingerJim一样,这是行不通的,因为参数引用被复制到本地成员-
t=Hash。在函数的另一次调用中,new
不会改变
t
。结果正如预期的那样,我认为doit的这两次调用在堆栈中有自己的内存空间。如果希望两个线程在一个对象上运行,请尝试将参数传递给该方法。就像doit(t)@GingerJim一样,这是行不通的,因为参数引用被复制到本地成员-
t=Hash。在函数的另一次调用中,new
不会改变
t
。“Private member”不是正确的术语,“local variable”是。啊,你和安德鲁的答案让我走上了正确的轨道。当然,这是由于范围的原因,与线程无关。好的,每个调用都位于内存中的其他地方,因为这两个调用自然是同时执行的。既然你先发帖,我会接受你的回答。非常感谢。“私人成员”不是正确的术语,“局部变量”是。啊,你和安德鲁的答案让我走上了正确的轨道。当然,这是由于范围的原因,与线程无关。好的,每个调用都位于内存中的其他地方,因为这两个调用自然是同时执行的。既然你先发帖,我会接受你的回答。非常感谢。“私人成员”不是正确的术语,“局部变量”是。啊,你和安德鲁的答案让我走上了正确的轨道。当然,这是由于范围的原因,与线程无关。好的,每个调用都位于内存中的其他地方,因为这两个调用自然是同时执行的。既然你先发帖,我会接受你的回答。非常感谢。“私人会员”不是正确的术语,“本地变量”