2014-02-27 23 views
0

我从一个线程试图例如在Ruby中下面的代码:睡眠和线程(红宝石)

count = 0 
arr = [] 

10.times do |i| 
    arr[i] = Thread.new { 
    sleep(count*10) 
    Thread.current["mycount"] = count 
    count += 1 
} 
end 

arr.each {|t| t.join; print t["mycount"], ", " } 
puts "count = #{count}" 

因为我增加每个线程睡眠,我希望输出是为了1-10 , 但是在几乎所有的运行中,顺序都是随机的。为什么?

+0

如果你想有一个同步的集合,你的问题是不是在你打算实现的目标明确,你可以找到在http上红宝石队列文档中使用Ruby的队列: //yard.ruby-doc.org/stdlib-2.1.0/Queue.html – bjhaid

回答

1

在线程完成休眠后,您只更新count,因此所有线程在睡眠时读取的初始值为count,即0。

也值得注意的是,以这种方式访问​​count不是线程安全的。

+0

谢谢!所以当我把睡眠放在后面时,我通常会按照我所寻找的顺序得到结果!然而,偶尔它仍然是无序的,这是因为我没有把我的计数同步? – user3358302

+0

是的,线程不能保证按照你开始的顺序运行。如果你想要这个不变量,你应该使用显式同步原语,因此其中一个后面编号的线程可以读取更小的count值。在这种情况下,通过将“count * 10”计算移出线程块,您可能会*得到所需的结果。但依靠这是危险的。 –

0

订单是随机的,因为对象count的访问在线程中不同步。

您遇到所谓的竞争条件

当两个或多个线程可以访问共享数据,他们试图在同一时间进行更改时,会发生竞争条件。

你可以通过在ruby中使用互斥锁,条件变量和队列对象来阻止它。

编辑:另外,看到杰里米的答案

+0

这很好,我认为这个例子的目的是演示没有同步的线程。不应该通过在每个线程上增加睡眠定时器来修正同步吗? – user3358302

+0

我想理论上大部分的时间都是真实的,但正如你所看到的,在现实中并不总是这样!另一个线程总有可能潜入其中。这不是你应该依赖的东西。同步是最好的,你可以完全相信你的解决方案的工作原理。 Queue对象最好,在Ruby中,如果我正确记得它有内置同步 – SparkyRobinson