title=スレッド


スレッドとはメモリ空間を共有して同時に実行される制御の流れです。
Ruby ではスレッドは[[c:Thread]] クラスのインスタンスとして表されます。


=== 実装
ネイティブスレッドを用いて実装されていますが、
現在の実装では Ruby VM は Giant VM lock (GVL) を有しており、同時に実行される
ネイティブスレッドは常にひとつです。
ただし、IO 関連のブロックする可能性があるシステムコールを行う場合には
GVL を解放します。その場合にはスレッドは同時に実行され得ます。
また拡張ライブラリから GVL を操作できるので、複数のスレッドを
同時に実行するような拡張ライブラリは作成可能です。

=== スケジューリング
Ruby のスレッドスケジューリングはネイティブスレッドのそれを利用しています。
よって詳細はプラットフォームに依存します。

=== メインスレッド

プログラムの開始と同時に生成されるスレッドを「メインスレッド」と呼
びます。なんらかの理由でメインスレッドが終了する時には、他の全てのスレッ
ドもプログラム全体も終了します。ユーザからの割込みによって発生した例外
はメインスレッドに送られます。

=== スレッドの終了

スレッドの起動時に指定したブロックの実行が終了するとスレッドの実行も終
了します。ブロックの終了は正常な終了も例外などによる異常終了も含みます。

===[a:exception] 例外発生時のスレッドの振る舞い

あるスレッドで例外が発生し、そのスレッド内で rescue で捕捉されなかっ
た場合、通常はそのスレッドだけがなにも警告なしに終了されます。ただ
しその例外で終了するスレッドを [[m:Thread#join]] で待っている他の
スレッドがある場合、その待っているスレッドに対して、同じ例外が再度
発生します。

  begin
    t = Thread.new do
      Thread.pass    # メインスレッドが確実にjoinするように
      raise "unhandled exception"
    end
    t.join
  rescue
    p $!  # => "unhandled exception"
  end

また、以下の 3 つの方法により、いずれかのスレッドが例外によって終
了した時に、インタプリタ全体を中断させるように指定することができま
す。

  * 組み込み変数 [[m:$DEBUG]] を真に設定する(デバッグモード)
    ruby インタプリタを -d オプション 付きで起動した場合も同様。
    (オプションの詳細に関しては[[d:spec/rubycmd]] を参照)
  * [[m:Thread.abort_on_exception]] でフラグを設定する。
  * [[m:Thread#abort_on_exception]] で指定
    したスレッドのフラグを設定する。

上記3つのいずれかが設定されていた場合、インタプリタ全体が中断されます。

=== スレッド終了時の ensure 節の実行

スレッド終了時には ensure 節が実行されます。
これはスレッドが正常に終了する時はもちろんですが、他のスレッドから [[m:Thread#kill]]
などによって終了させられた時も同様に実行されます。[[m:Thread#kill!]] が呼ばれた時は
ensure 節が実行されません。

ただしメインスレッドに対して [[m:Thread#kill!]] が呼ばれても ensure 節が実行されます。
メインスレッドの終了時の詳細に関しては [[d:spec/terminate]] を参照して下さい。

=== スレッドの状態

個々のスレッドは、以下の実行状態を持ちます。これらの状態は
[[m:Object#inspect]] や
[[m:Thread#status]] によって見ることができます。

 p Thread.new {sleep 1} # => #<Thread:0xa039de0 sleep>

: run (実行or実行可能状態)
 生成されたばかりのスレッドや [[m:Thread#run]] や
 [[m:Thread#wakeup]] で起こされたスレッドはこの状態です。
 [[m:Thread#join]] でスレッドの終了を待っているスレッドもスレッドの
 終了によりこの状態になります。
 
 この状態のスレッドは「生きて」います。

: sleep (停止状態)
 [[m:Thread.stop]] や [[m:Thread#join]] により停止されたスレッ
 ドはこの状態になります。
 
 この状態のスレッドは「生きて」います。

: aborting (終了処理中)
 [[m:Thread#kill]] 等で終了されるスレッドは一時的にこの状態になりま
 す。この状態から停止状態(sleep)になることもあります。
 
 この状態のスレッドはまだ「生きて」います。

: dead (終了状態)
 [[m:Thread#kill]] 等で終了したスレッドはこの状態になります。この状
 態のスレッドはどこからも参照されていなければ GC によりメモリ上から
 なくなります。
 
 この状態のスレッドは「死んで」います。


=== デッドロックの検出
