2016年2月3日水曜日

異なるクラスのスレッド間で同期させる

久しぶりの投稿

当初はあるクラスのスレッド間で1秒ごとにシーケンシャル処理を行いたいというものだった。

# a.rb
class A
  @m = Mutex.new

  def get
    self.class.instance_variable_get(:@m).synchronize do
      sleep 1
      puts "#{Time.now} => #{self.class.name}"
    end
  end

end

# do.rb
require_relative './a'
require_relative './b' # Aとはクラス名のみ異なる。

ps = [A, B]
ts = []

5.times do
  ps.each do |prog|
    t = Thread.new do
      prog.new.get
    end

    ts << t
  end
end

ts.each { |t| t.join }

do.rbの実行結果は次のとおり。

$ ruby do.rb 
2016-02-03 18:10:30 +0900 => A
2016-02-03 18:10:30 +0900 => B
2016-02-03 18:10:31 +0900 => B
2016-02-03 18:10:31 +0900 => A
2016-02-03 18:10:32 +0900 => B
2016-02-03 18:10:32 +0900 => A
2016-02-03 18:10:33 +0900 => A
2016-02-03 18:10:33 +0900 => B
2016-02-03 18:10:34 +0900 => B
2016-02-03 18:10:34 +0900 => A

  • Aのスレッド間では1秒ごとにメソッドが実行されている。
  • Bのスレッド間では1秒ごとにメソッドが実行されている。
ただ、この全部のスレッドで1秒ごとに処理を実行したいという変更が入ったため変更。
今回はモジュール変数で対応した。


# synchronizable.rb
module Synchronizable
  @@m = Mutex.new

  def m
    @@m
  end
end

# a2.rb

require_relative './synchronizable'

class A2
  include Synchronizable

  def get
    m.synchronize do
      sleep 1
      puts "#{Time.now} => #{self.class.name}"
    end
  end
end

# do2.rb
require_relative './a2'
require_relative './b2' # A2とはクラス名のみ異なる

ps = [A2, B2]
ts = []

5.times do
  ps.each do |prog|
    t = Thread.new do
      prog.new.get
    end

    ts << t
  end
end

ts.each { |t| t.join }

do2.rbの実行結果

$ ruby do2.rb 
2016-02-03 18:24:44 +0900 => B2
2016-02-03 18:24:45 +0900 => B2
2016-02-03 18:24:46 +0900 => A2
2016-02-03 18:24:47 +0900 => A2
2016-02-03 18:24:48 +0900 => A2
2016-02-03 18:24:49 +0900 => B2
2016-02-03 18:24:50 +0900 => A2
2016-02-03 18:24:51 +0900 => B2
2016-02-03 18:24:52 +0900 => A2
2016-02-03 18:24:53 +0900 => B2

すべてのスレッドで1秒ごとに処理が実行されている。

0 件のコメント:

コメントを投稿