scramble cadenza

技術ネタのガラクタ置き場

ruby の Thread に関する不思議な現象

イントロ

第19章 スレッド を見てやってみました。 が、うまくいかない。

わかる

% cat thread.rb                                                                                                              
Thread.fork {
    while true
      puts 'forked thread'
    end
}
while true
  puts 'main thread'
end

% ruby thread.rb
#=> 
forked thread
forked thread
forked thread
main thread
main thread
forked thread
forked thread

混ざって出てくる。

わからない

% irb
Thread.fork {
    while true
      puts 'forked thread'
    end
}
while true
  puts 'main thread'
end
#=>
forked thread
forked thread
forked thread
...

irb, pry などでコードをコピペすると混ざらない。

言いたいこと

なんでこうなる? 何故挙動が違う?

やったこと

      @scanner.each_top_level_statement do |line, line_no|
        signal_status(:IN_EVAL) do
          begin
            line.untaint
            @context.evaluate(line, line_no)
            output_value if @context.echo?
            exc = nil
          rescue Interrupt => exc
          rescue SystemExit, SignalException
            raise
          rescue Exception => exc
          end

この辺りで line を input として受け取って、 eval して、 output している。問題は出力部分。

    def output_value # :nodoc:
      printf @context.return_format, @context.inspect_last_value
    end

output_value で、printf している。特に port 指定はないので、標準出力されているはず。

  • thread について調べまくった
    • 結論は「IO 待ちが発生するなら Thread が入れ替わる(なはず...)」
    • つまり printf なら僅かながら IO 待ちが発生するので、出力は混ざるはず。

現在

  • 解せなくて気持ちが悪い

環境