5.6.0において導入された新しいPerlスレッドの特徴を説明するものである。このモデルにおいては、それぞれのスレッドはそれら自身のPerlインタープリタで実行され、スレッド間で共有するデータも明示的でなければならない。possible.Perlのバージョン5.005で使われていた、5.005モデルと呼ばれる別の古いスレッド様式がある。この古いモデルは問題があることが知られていて、非推奨である。バージョン5.10がリリースされるころには無くなるであろう。できるだけ速やかに既存の5.005スレッドを新しいものに移行することが強く勧められる。-VでPlatformセクションを見れば、どちらのスレッド様式があるのか(あるいは無いのか)を知ることができる。useithreads=defineとなっていればiスレッドをサポートしているし、use5005threads=defineとあれば5.005スレッドだ。両方とも出ない場合、あなたのPerlはスレッドをサポートしていない。両方ある場合は問題がある。classを通じてなされる。この場合の変化に注意すること。利用できるようになっていて、安定している。class群)は5.8.0で登場した。全ての新しい特徴同様、注意が必要ではあるとはいえ、これも安定している。point.スレッドとはプログラム内を流れる単一の実行項点を持った制御のフローである。why.こういうと非常に多くの点でプロセスに似ているように聞こえるだろう。確かにそのとおりで、スレッドはひとつのプロセスにおける細かい部分の一つだ。全てのプロセスは少なくとも一つのスレッドを持つ。これまでは、Perlを走らすプロセスは全てただ一つのスレッドを持っていた。5.8になって、余分にスレッドをつくることができるようになった。それがいつどのように、いかにしてなされるのかをこれから観ていこう。program.スレッドプログラムを構築する3つの基本的な方法がある。どのモデルを選ぶかはプログラムに何をやらせるかに依存する。多くの重要なスレッドプログラムにおいて、プログラム中の異なる部分に異なるモデルを利用したいと思うだろう。thread.ボス・ワーカーモデルでは通常、一つの「ボス」スレッドと、一つ以上の「ワーカー」スレッドを持つ。ボススレッドは必要とされるタスクを集約ないし生成する。それからそれらのタスクを適したワーカースレッドに分配する。event.このモデルはGUIとサーバプログラムに共通である。そこではメインスレッドがイベント発生を待ち、処理のために適したワーカースレッドにイベントを渡す。ひとたびイベントが渡されると、ボススレッドは次のイベントのために待機する。times.ボススレッドは相対的に仕事量は少ない。タスクは必ずしも他の方法を使ったものより早く実行される必要がないにもかかわらず、もっともユーザーレスポンスタイムが良くなる傾向にある。data.仕事仲間モデルでは、データの様々な部分に対し本質的に同じ作業を行ういくつかのスレッドがつくられる。これは、プロセッサの巨大な配列が多くのデータ片に対して全く同じことを行う古典的な並列処理やベクトル処理とそっくりである。feedback.プログラムを走らせているシステムが異なるプロセスをまたぐマルチスレッドを分配するような場合には、このモデルは殊のほか便利である。レイトレースやレンダリングエンジンといった、個々のスレッドがユーザにフィードバックするために一時的な結果をもたらすような場合にも便利であろう。line.パイプラインモデルはあるタスクを何段階の処理の連続へと分ける。一つのステップの結果を次の処理を行うスレッドへと渡す。それぞれのスレッドはデータの各部分に対し一つのことを行い、結果を次のスレッドへ渡す。processor.しばしば他の文脈でも同じぐらいの意味があるのだが、二つ以上のスレッドが並列に処理を行うように、あなたがマルチプロセッサを持っているならば、このモデルは最も意味がある。それは、あるパイプラインの一部が進行中の間に、他のパイプラインの一部が(例えばI/Oやシステムコール)をブロックするのを許可するのと同様に、個々のタスクを小さく単純なものに留める傾向がある。違うプロセッサ上で別々のパイプラインを走らせるならば、それぞれのプロセッサのキャッシュを利用するという利益を得ることができるだろう。on.)このモデルはまた、自分自身を呼び出すサブルーチンを抱えるよりも、別のスレッドを生み出すような再起的プログラムの形態に利用しやすい。素数やフィボナッチ数列ジェネレーターは、どちらもこのパイプラインモデルの形態にうまく位置付けられる(素数ジェネレーターは後で登場する)。sophisticated.あるシステムにスレッドを実装するには様々なやり方がある。してスレッドを実装するかという問題は、ベンダーと、場合によってはオペレーティングシステムのバージョンとの両方に依存している。最初の実装は比較的単純であろうが、OSのバージョンが上がるにつれてより洗練されていくだろう。it.このセクションに書かれている情報は役に立つとはいえ、必須ではない。感じたなら読み飛ばしてもかまわない。threads.スレッドには三つの基本的なカテゴリーがある。ユーザーモードスレッド、カーネルスレッド、そしてマルチプロセッサカーネルスレッドだ。process.ユーザーモードスレッドとは、完全にプログラムとライブラリの中に存在するスレッドである。このモデルにおいては、OSはスレッドについて何も関知しない。OSからしてみる限り、あなたのプロセスはただのひとつのプロセスである。sleep().これは最も簡単なスレッドの実装であり、ほとんどのOSが最初にとったやり方である。この方法の大きな欠点は、OSがスレッドに関知していないために、もしも一つのスレッドがブロックをしたら、全てのスレッドがブロックしてしまうということだ。典型的なブロック行為には、ほとんどのシステムコール、ほとんどのI/O、そしてsleep()のようなものが含まれる。level.カーネルスレッドは進化の第二段階だ。OSはカーネルスレッドについて知っていて、その許可を出す。カーネルスレッドとユーザーモードスレッドの主要な違いは、ブロッキングについてである。カーネルスレッドでは、一つのスレッドをブロックした事が他のスレッドまでブロックしたりはしない。このようなことは、ユーザーモードスレッドにおいてはなりたたない。ユーザーモードでは、カーネルがブロックするのはプロセスレベルであって、スレッドレベルではないからだ。have.これは大きな前進であり、非スレッドプログラムに対し、スレッドプログラムが大きなパフォーマンスの向上を得ることを可能にしている。I/Oの実行をブロックするスレッドは、他のことを行うスレッドをブロックしないだろう。システムがいくつCPUを備えているかに関係なく、それぞれのプロセスはいまだに一度に一つのスレッドしか走らせない。stored.カーネルのスレッド制御がいつでも割り込めるので、あなたがプログラム中につくった暗黙のロックの前提が白日の下にさらけ出してしまうだろう。2のような単純なものでも、$aが他のスレッドからみえるならば、右辺の値を取り出す時間と新しい値を格納する時間の間に、他のスレッドが$aを変えてしまって、あなたの予期しない振る舞いをしうる。CPUs.マルチプロセッサカーネルスレッドは、スレッドのサポートにおける最終段階である。一台のマシンが複数のCPUを持っているマルチプロセッサカーネルスレッドでは、OSは別々のCPU上で同時に複数のスレッドを走らせるようにスケジュール管理をするだろう。vengeance.一つ以上のスレッドが同時に実行するので、これによりスレッドプログラムは飛躍的なパフォーマンスの向上を得ることができる。引き換えに、基本的なカーネルスレッドでは現れなかったであろうイライラするような同期性の問題が一気に姿を現す。ways.スレッドを備えるOSの違いというレベルに加えて、それぞれのOSは(そしてそれぞれのスレッド実装は)それぞれの方法でもってCPUサイクルをスレッドに割り当てる。chooses.次の二つのうちの一つが起こる場合、協調的マルチタスクシステムは実行中のスレッドに制御を明け渡させる。あるスレッドがyield関数を呼び出すと、制御を明け渡す。スレッドがI/Oの実行などのブロックを引き起こすような何かを行う場合も、制御を明け渡す。協調的マルチタスクシステムの実装においては、そのように選択するならば、一つのスレッドが他の全てのスレッドのCPU時間を食い尽くすことができる。CPU.プリエンティブなマルチタスクシステムは、次にどのスレッドを実行するか決めながら、一定の間隔でスレッドに割り込みをいれる。preemptively.)あるシステムにおいては、協調的スレッドとプリエンティブなスレッドを同時に実行することができる(例えば、通常のプライオリティを持ったスレッドがプリエンディブに振舞うのに対して、リアルタイムのプライオリティを持ったスレッドはしばしば協調的に振舞う)。both.もしもあなたが他のスレッドの実装を経験したことがあるなら、事態は全くあなたの予想とは違うことがわかるだろう。Perlスレッドを扱う時には、”PerlスレッドはXスレッドではない”(Xはどんな値でもよい)ということを覚えておくことが重要だ。it.これは、これまで登場してきたあらゆるスレッドとPerlスレッドが完全に異なるということを言っているのではない。Perlスレッドは他のモデル、特にPOSIXスレッドに多くを負っている。PerlがCではないように、PerlスレッドはPOSIXスレッドではない。あなたがミューテックスやスレッドプライオリティを期待しているならば、ちょっと立ち戻って、自分が何をしたいのか、Perlはいかにしてそれが可能なのかを考える時だ。well.しかし、あなたのシステムのスレッドが許可していなければ、Perlスレッドが魔法のようにそれを行うなんてことはできないことを覚えておくことが重要だ。システムがsleep()でプロセスを丸ごとブロックするなら、Perlも普通にそうするだろう。Different.Perlスレッドは別ものなのだ。code.スレッドの追加はPerlの内部的な実態を変化させてしまった。これにはXSモジュールや外部ライブラリーを書いている人々も含まれる。デフォルトではスレッド間でperlのデータは共有されない。そのためPerlモジュールはスレッドセーフであるという機会に恵まれているし、あるいは容易にスレッドセーフにすることができる。スレッドセーフの札がついていないモジュールは製品版の前にテストされるかコードレビューを受けるべきである。thread-safe.あなたが使おうとしているモジュールの全てがスレッドセーフというわけではないし、モジュールのドキュメントに安全であると書かれていないならば、常に安全ではないものと仮定するべきである。このことは、perlのcore部分として配布されているモジュールにもあてはまる。スレッドは新しい機構なのであり、標準モジュールの中にさえスレッドセーフでないものがある。environment.仮にあるモジュールがスレッドセーフであったとしても、そのモジュールがうまく働くように最適化されているということを意味するわけではない。できるだけスレッド環境でパフォーマンスが向上するように、スレッド化されたPerlの新機構を利用するようモジュールを書き直したほうがよい。semaphores".もしもなんらかの理由でスレッドセーフではないモジュールを使っているならば、ただ一つのスレッドからそれを使うことによって防ぐことができる。そのようなモジュールにアクセスするマルチスレッドが必要ならば、セマフォやアクセスを制御するためのプログラミング原則を用いることができる。セマフォは"ベーシックなセマフォ"でカバーしている。Libraries".また、"システムライブラリにおけるスレッドの安全性"を参照のこと。easier.中核となるthreadsモジュールは、あなたがスレッドプログラムを書くのに必要となる基本的な機能を提供する。次からのセクションでは、スレッドプログラムを作るのに必要なことを示しながら基礎的なところをカバーしていこう。fail.スレッドのサポートは、あなたのプログラムがコンパイルされる時ではなく、Perlのコンパイル時のオプションによる。Perlをビルトするときに、サポートのオン・オフを行う。スレッドがサポートされるようにPerlがコンパイルされていないなら、スレッドを使用する試みは失敗するだろう。like:スレッドが使用可能かどうかをチェックするためにConfigモジュールを利用することができる。this:スレッドを利用するかもしれないモジュールを使うプログラムには、次のようなコードをつけておくとよい。Perl.スレッド機構の有無に関わらず走るようなコードは通常、非常に繁雑なものになるので、モジュール内にてスレッド専用のコードは分離しておくのがベストだ。上の例では、MyMod_threadedがそれで、スレッド可能なPerl上で走るときだけインポートされる。problem.スレッドのサポートが安定しているとはいえ、下の例を試すときには、あなたを驚かせるような奇妙なことがまだたくさんおきる。実際の状況下では、プログラムが終了する前に全てのスレッドが実行を終えることに注意を払わなければならない。簡明さを重視しているのでここで取り上げる例においては、そのような注意を払っていない。これらの例を”そのまま”実行すると、プログラムが終了する際にまだスレッドが走っているという理由で常にエラーメッセージがはき出されるだろう。この警告は気にしなくて良い。今後のPerlのバージョンではこの問題は取り除かれるであろう。threads.threadsパッケージは新たなスレッドを生成するのに必要なツールを提供する。他のモジュール同様、それを使いたいとPerlに伝えればよい。よって基本的なスレッドを生み出すのに必要な全ての部品がインポートされる。メソッドはサブルーチンへのリファレンスを引数にとって新しいスレッドを生成する。このスレッドはリファレンスされたサブルーチンの実行を開始する。このとき制御はサブルーチンと呼び出し側との両方に渡される。this:もし必要ならばスレッド開始時のサブルーチンにパラメータを渡すことができる。呼び出しにパラメータのリストを含める。arguments.この例はスレッドのもう一つの特徴を示している。同じサブルーチンを利用するいくつものスレッドを生成することができるのだ。それぞれのスレッドは同一のサブルーチンを実行するが、それぞれのスレッドはそれぞれ別々の環境と引数をとることができる。processor.あるスレッドが明示的に他のスレッドへとCPUを譲り渡せられたら便利だと思うことがあるだろう。あなたのスレッドパッケージはプリエンティブなマルチタスク機能をサポートしていないかもしれない。プロセッサ・インテンシブなことをしようとしているかもしれないし、ユーザーインターフェースのスレッドがしょっちゅう呼び出されることを確認したいと思うかもしれない。スレッドがプロセッサを明け渡せたらなあということがよくある。this:Perlのスレッドパッケージはこれを実現するyield()関数を提供している。yield()はとても素朴で、このように動作する。platform.yield()はCPUを明け渡すためのヒントでしかない。実際に何が起こるのかということは、ハードウェアやOS、そしてスレッドライブラリに依存している。それゆえ、yield()を呼び出すスレッドのスケジューリングをたてるべきではないことに注意することが大切だ。method:スレッドはサブルーチンでもあるから、値を返すことができる。スレッドが終了して何らかの戻り値を得るのを待つために、join()を使うことができる。next.上の例では、スレッドが終了するやいなjoin()メソッドが戻る。スレッドの終了と、返すべき値を収集するための待機に加えて、join()はスレッドが必要とするOSレベルの掃除を実行する。長時間にわたって実行されるプログラムが大量のスレッドを生成する場合には。戻り値を必要とせず、スレッドの終了を待つ必要もなければ、かわりに次に説明するdetach()メソッドを呼び出すべきだ。done.join()は三つのことを行う。スレッド終了の待機、その後の掃除、そしてスレッドが生み出したであろうデータを返すこと。スレッドが返す値に関心がなく、いつスレッドが終了するのかを実際には気にしない場合には?必要なのはスレッドが掃除されることだけだ。automatically.このような場合、detach()メソッドを使う。ひとたびスレッドがdetachされると、スレッドは終了するまで実行し続け、そのあとPerlが自動的に掃除をする。lost.ひとたびあるスレッドがdetachされたら、そのスレッドはjoinされないだろう。(joinのために待機しても)スレッドが生成したであろうデータは失われる。about.いまやスレッドの基本部分については見終わった。スレッドを扱うことは、非スレッドプログラムが心配しなくてよかったデータアクセスに対する二つの複雑さを導入することになる。5.005型スレッドの間の(もっといえば、そこから外れる多くのスレッドシステムにとっての)最大の違いは、デフォルトでデータが共有されないという点だ。新しいperlスレッドが生成されるとき、現在のスレッドに関連する全てのデータは新しいスレッドにコピーされる。続いてそのデータは新しいスレッド内でプライベートなものとなる!これはUNIXのプロセスがforkするときに起きることと似ている。この場合、実際のforkではメモリ上での置き換えが起こるのに対して、そのデータは同一プロセッサ内の違うメモリ部分にコピーされるだけであるという点は除く。attribute:しかしスレッド機能を利用するならば、通常はスレッド間で少なくともある程度は同一のデータを共有したいものだ。shared属性によってなされる。example:共有化された配列の場合は、配列の要素全てが共有化される。共有化された配列やハッシュの要素に代入するものに対しては制限がある。単純な値や共有化された変数へのリファレンスは可能だ。これは、局所化された変数が図らずも共有化されることがないからだ。不正な代入はスレッドを殺してしまうだろう。