ruby是否具有Java等效的synchronize关键字?我使用的是1.9.1,我看不太优雅。
答案 0 :(得分:15)
它没有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
答案 1 :(得分:10)
接受的答案并不代表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
的部分状态将无法预测。
现在我们将这些操作称为 atomic :
#! /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。