多个线程调用相同的功能

假设我们有多个线程都调用相同的函数:

def foo 
  # do stuff ...
end

100.times do |i|
  Thread.new do
    foo
  end
end

如果两个或多个线程当前位于foo ,它们是否在foo内共享相同的局部变量?

这与我的第二个问题有关。 线程是否有单独的堆栈帧,还是共享单个进程中的堆栈帧? 特别是,当多个线程分别调用foofoo返回之前,堆栈中是否有多个foo副本,每个都有自己的局部变量,或者在堆栈中只有一个foo副本?


是的,他们共享相同的变量。 这是线程的一个关键元素,在只读上下文中很好,但如果他们写入任何这些变量,则需要使用Mutexsynchronize这些线程,因此只有一个可以在任何给定时间更改变量。 有时他们可能会调用间接更改数据的方法,因此在决定是否需要同步之前,您需要充分了解系统。

至于你的第二个问题,如果我明白你在问什么,他们有单独的堆栈帧,但它们仍然在内存中共享相同的数据。

在下面的例子中,澄清局部变量zip由多个线程共享,因为它是在当前作用域中定义的(线程不会更改作用域,它们只是在当前作用域中启动一个单独的并行执行线程)。

zip = 42

t = Thread.new do
  zip += 1
end

t.join

puts zip # => 43

这里的加入节省了我,但是如果我保留那里的话,显然这根本就没有任何意义。 如果我要做以下事情会很危险:

zip = 42

t = Thread.new do
  zip += 1
end

zip += 1

puts zip # => either 43 or 44, who knows?

这是因为你基本上有两个线程同时尝试修改zip 。 当您访问网络资源或增加数字等时,这会变得很明显,如上所述。

然而,在下面的例子中,局部变量zip是在一个全新的范围内创建的,所以这两个线程实际上并不是同时写入同一个变量:

def foo
  zip = 42
  zip += 1 # => 43, in both threads
end

Thread.new do
  foo
end

foo

有两个并行堆栈被管理,每个堆栈在foo方法中都有自己的局部变量。

但是,下面的代码是危险的:

@zip = 42 # somewhere else

def foo
  @zip += 1
end

Thread.new do
  foo
end

foo

puts @zip # => either 43 or 44, who knows?

这是因为实例变量@zip可以在foo函数的作用域之外访问,所以两个线程都可以同时访问它。

'两个线程同时改变相同数据'的这些问题可以通过在改变变量的代码部分周围使用仔细放置的Mutexes(锁)来解决。 必须在创建线程之前创建互斥锁,因为在互斥锁的情况下,两个线程访问相同的互斥锁(在设计上)至关重要,以便知道它是否被锁定。

# somewhere else...
@mutex = Mutex.new
@zip   = 42

def foo
  @mutex.synchronize do
    @foo += 1
  end
end

Thread.new do
  foo
end

foo

puts @zip # => 44, for sure!

如果当执行流到达Mutex#synchronize行时,它会尝试锁定互斥锁。 如果成功,则进入该块并继续执行。 块完成后,互斥锁再次解锁。 如果互斥锁已经被锁定,线程会一直等到它再次变为空闲状态......这实际上就像一扇门,一次只能有一个人走过。

我希望这可以清除事情。


在方法中定义的局部变量不共享。 但是,如果线程处于线程块的范围内,则可以访问同一对象的实例变量。

例如:

def foobar
    puts "Foo is defined!" if defined?(foo)=='local-variable'
    foo = 5
end

如果被多个线程调用,则永远不会放置该字符串。

但是以下需要一个互斥体来同步,因为竞争条件适用:

foo = {bar:5}
def foobar(value)
    value[:bar]+=5
end
15.times{|i| Thread.new{foobar foo}}

在此之后,foo [:bar]可能包含值35,因为foobar的每次调用都会更改散列值foo中的值。

链接地址: http://www.djcxy.com/p/59167.html

上一篇: Multiple threads calling the same function

下一篇: Bootstrap menu not displaying properly in mobile mode