ruby是否具有Java等效的synchronize关键字?

Zom*_*ies 12 ruby multithreading synchronize

ruby是否具有Java等效的synchronize关键字?我使用的是1.9.1,我不太看到这样做的优雅方式.

Chr*_*nch 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
Run Code Online (Sandbox Code Playgroud)

  • 如果您不想,也不必从Monitor继承.只需在您的课程中包含MonitorMixin模块(也可以通过`require'monitor'来引入),您就可以免费获得相同的行为. (9认同)
  • 这是一个通用的编程语言设计原则:只有糟糕的编程语言需要关键字或新的语言功能.精心设计的语言可以在库中完成. (7认同)
  • @JörgWMittag看起来我们找到了一个LISP程序员;) (2认同)

sky*_*der 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
Run Code Online (Sandbox Code Playgroud)

在输出中你会得到像这样的东西:

before (1): 0
after (1): 1
before (2): 0
before (0): 0 <- !!
after (2): 2
after (0): 3 <- !!
Total: 3
Run Code Online (Sandbox Code Playgroud)

线程(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
Run Code Online (Sandbox Code Playgroud)

输出:

before (1): 0
after (1): 1
before (0): 1
after (0): 2
before (2): 2
after (2): 3
Total: 3
Run Code Online (Sandbox Code Playgroud)

现在,通过使用synchronize块,我们确保添加操作的原子性.

但线程仍以随机顺序运行(1-> 0-> 2)

有关详细说明,您可以继续阅读本文.