Ruby有没有Java中synchronize关键字的等价物?我正在使用1.9.1版本,但我并没有看到一种优雅的方法来实现这个。
Ruby有没有Java中synchronize关键字的等价物?我正在使用1.9.1版本,但我并没有看到一种优雅的方法来实现这个。
虽然它没有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'
会同时引入它),你就能免费获得相同的行为。 - Chucksynchronize do
,但答案仍然是“200_000”。这里的诀窍在哪里? - skywindersynchronize
的工作原理。https://dev59.com/dnA75IYBdhLWcg3wlqSh#30840316 希望它有助于感受到差异。 - skywinder被接受的答案并不代表同步的工作方式!
你只需将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)。
有关详细解释,请继续阅读此文章。