【发布时间】:2011-03-13 14:46:04
【问题描述】:
ruby 是否有 Java 等效的 synchronize 关键字?我正在使用 1.9.1,但我并没有看到一种优雅的方式来做到这一点。
【问题讨论】:
标签: ruby multithreading synchronize
ruby 是否有 Java 等效的 synchronize 关键字?我正在使用 1.9.1,但我并没有看到一种优雅的方式来做到这一点。
【问题讨论】:
标签: ruby multithreading synchronize
它没有synchronize 关键字,但您可以通过Monitor 类获得非常相似的东西。下面是 Programming Ruby 1.8 书中的一个示例:
require 'monitor'
class Counter < Monitor
attr_reader :count
def initialize
@count = 0
super
end
def tick
synchronize do
@count += 1
end
end
end
c = Counter.new
t1 = Thread.new { 100_000.times { c.tick } }
t2 = Thread.new { 100_000.times { c.tick } }
t1.join; t2.join
c.count → 200000
【讨论】:
require 'monitor' 引入)包含在您的课程中,您就可以免费获得相同的行为。
synchronize do,答案还是一样:200_000。诀窍在哪里?
synchronize 的工作原理。 stackoverflow.com/a/30840316/1698467希望能有所帮助。
接受的答案并不代表synchronize 的工作原理!
您可以注释掉 synchronize do 并运行已接受答案的脚本 - 输出将是相同的:200_000!
所以,这里有一个例子,来展示使用/不使用synchronize 块运行之间的区别:
#! /usr/bin/env ruby
require 'monitor'
class Counter < Monitor
attr_reader :count
def initialize
@count = 0
super
end
def tick i
puts "before (#{ i }): #{ @count }"
@count += 1
puts "after (#{ i }): #{ @count }"
end
end
c = Counter.new
3.times.map do |i|
Thread.new do
c.tick i
end
end.each(&:join)
puts c.count
在输出中你会得到类似的东西:
before (1): 0
after (1): 1
before (2): 0
before (0): 0 <- !!
after (2): 2
after (0): 3 <- !!
Total: 3
当线程(0)启动时,count等于0,但添加+1后其值为3。
当线程启动时,它们会看到 count 的初始值。但是当他们每个人都尝试添加+1时,由于并行计算,值变得不同。如果没有适当的同步,count 的部分状态是不可预测的。
现在我们将这些操作称为原子:
#! /usr/bin/env ruby
require 'monitor'
class Counter < Monitor
attr_reader :count
def initialize
@count = 0
super
end
def tick i
synchronize do
puts "before (#{ i }): #{ @count }"
@count += 1
puts "after (#{ i }): #{ @count }"
end
end
end
c = Counter.new
3.times.map do |i|
Thread.new do
c.tick i
end
end.each(&:join)
puts c.count
输出:
before (1): 0
after (1): 1
before (0): 1
after (0): 2
before (2): 2
after (2): 3
Total: 3
现在,通过使用synchronize 块,我们确保了添加操作的原子性。
但线程仍以随机顺序运行 (1->0->2)
详细解释,您可以继续阅读this article。
【讨论】: