マルチスレッド難しい

アルバイト先からAmazon.co.jp: dRubyによる分散・Webプログラミング: 関 将俊: 本を借りてマルチスレッドのプログラムを久しぶりに書いた。
もうデットロックしまくりで困る。rubyは言語レベルのスレッドだからなのかすべてのスレッドが停止するとデットロックとして検出してくれる。高性能だねぇ。

本の中でバリア同期の実装が紹介されていたけど、rindaを使うことが前提なので自分で使わないバージョンを作ってみた。(rindaについてはRuby Reference Manual - るりま)popのブロックを積極的に利用している。

require 'thread'

class LocalBarrier
   def initialize(n)
      @n = n
      @waits = Queue.new
      @block = Queue.new
   end
   def sync(current)
      @waits.push(current)
      @block.push(true) if @waits.length == @n
      @block.pop
      @block.push(true)
   end
end

n個itemがたまったら同期が完了したことになる。Queueにはtopメソッドが存在しないので、popしたあとpushし直している。
rinda版見たく実装するためにはmutexをつかってちゃんと実装しないとだめっぽいなぁ。[key, 0]で待ってるrinda版は確かにかっこいいよ。

第二案。トリッキーではない。

require 'thread'

class LocalBarrier
   def initialize(n)
      @n = n
      @waits = Queue.new
   end
   def sync
      if @waits.length == @n - 1
         until (@waits.empty?) do
            @waits.pop.wakeup
         end
      else
         @waits.push(Thread.current)
         Thread.stop
      end
   end
end