[[藤井のスタートページ]] *序 [#e19b6173] 一般に GUI (Graphical User Interface) が使われるようになると、 Programming 的には multi-thread を使う機会が増えるように思う。 その主たる理由は、本体の program の実行中に user が graphical window を通じて様々なことをやろうとする(window のサイズを変えるとか 中止のボタンを押すとか)のを受け付けてやる必要がある点であろう。 本体の program の終了まで、これらの操作が受け付けられないのは 困る。そこで、本体は別 thread として動かし、user の要求の受付は 常時行うようにするのが自然な program 設計であろう。 例えばデータ収集プログラムでは、データ収集開始の指示が出されたら、 データ収集の部分、すなわち測定器からのデータを読み取り、記録し 必要ならモニタデータを表示する部分は別 thread として起動し、 ユーザの操作(一時停止、再開、終了など)は常時受け付ける状態に するのが自然な書き方であろう。 *Threadの生成 [#f9974160] Threadの生成は、POSIX系のOSでは pthread_create、Windowsであれば CreateThread(この他にも _beginthread や _beginthreadex なども ある)で行う。いずれもthreadの開始とともにstartする関数のaddressを 与える。この関数は引数を一つとることができ、通常は必要なparameter など(のセット)のaddress を与える。この引数についてもthread生成 関数の引数で与える。 Thread生成時の状態はthread生成関数の引数の一つとして 与えるthread attributesで決まる。生成と同時に開始するか、 生成時は一時停止状態で、開始の指示は後から与えるかが 選択できる。 **Threadとの通信 [#rf4fe0ef] Threadは同一process内で動いているので、main threadとmemory共有が 可能である。従って、排他制御が必要でなければ通信は比較的容易に できる。ただし、共通に使う変数に関しては他所で値を変える可能性が あることをcompilerに示唆するためvolatile宣言を付加しておく。 一般に共有変数に対し排他制御が必要になるような使い方は極力避ける べきである。排他制御とdeadlockは表裏一体である。 **Threadの状態の把握 [#eea90d64] Threadの状態、特に終了したか否かをmain threadから知りたい場合が 多々ある。特にprogram全体を穏やかに終了するには子threadが終了 しているかどうか知りたい。 Threadの状態を示す共有変数を用意するのも一つの方法で あるがWindowsの場合は、POSIXのselectに似たsmartな やり方が用意されている。 Windowsのthread生成関数であるCreateThread関数は、HANDLEを返す。 このHANDLEはsignalを持っていて、このHANDLEがsignal状態になった時、 threadは終了している。Windowsにはsignal状態になるのを待つ関数が 用意されている(WaitForSingleObject、WaitForMultipleObjects等)ので、 これを使って子threadの終了を待ってmain thread を終了するという芸当が簡単にできる。 POSIX thread では pthread_join() 関数を用いて thread の終了を 待つことはできる。しかし「複数 thread のうちどれか一つが終了したら」 などという待ち方は pthread_join() だけではできない。 **C++とthread start routine [#r88b96ea] いくつものthreadを生成したい時、似たような処理を繰り返すことになる ので、C++であればbaseとなるthread classを作って、そこから別classを 派生させobjectを生成したくなる。この時問題になるのがstart routine で、これはstatic関数でなければならない。Object生成前に関数実体が 存在していなければならないからである。