pubDate: 2024-05-30
author: sakakibara
pthreadはCで使われるスレッドライブラリであり、POSIXスレッドとも呼ばれる。 pthreadでよく使われる関数は以下の通りである。
pthread_create: スレッドを作る。
pthread_exit: スレッドを終了する。
pthread_join: スレッドの終了を待つ。
pthread_self: 自分自身のスレッドIDを取得する。
pthread_equal: スレッドIDが等しいかどうかを調べる。
pthread_cancel: スレッドをキャンセルする。
特に最初の3つだけで基本的にはスレッドを使うことができる。 最後の3つのうち上2つは使い方が簡単なので説明はせず、最後の一つはそもそも使用することがプログラミングスタイル的に推奨できないので説明はしない。
以下ではpthread_create
を使っている。使い方についてはmanを見ろという感じ。
重要なことはpthread_create
はスレッドを作成した後、作成したスレッドの終了を待つことなく、すぐに帰ってくる。
元のスレッドと新しいスレッドがどの順番で実行されるかはOSの気まぐれである。
なお、pthread_create
の第一引数はスレッドIDを格納する変数であり、int型(pthread_t
)である。
ここで、ThreadFunc
は6
回ループするが、main
は3
回ループしない。実際に実行してみると、I'm threadFunc
が3
回しか表示されないことがわかる。
通常、main関数が終了すると、そのプロセスが終了する。 そのプロセスが終了すると、そのプロセスにおけるスレッドも終了する。
プロセスに対して全てのスレッドは対等であり、 どのスレッドからプロセス終了のシグナルが送られてきてもそのプロセスは終了する。
スレッドはコールバック関数がreturnすると終了する。
また、pthread_exit
を使うことでその関数をよびだしたスレッドのみを終了させることができる。
これはいわゆるbreak
のようなものであり、入れ子になった呼び出しでも終了させることができる。
スレッドで複数の処理をさせて、その結果をまとめたい場合があるだろう。 他の処理を待ってから次の処理を行いたい場合である。
pthread_join
はスレッドの終了を待つ関数である。
この関数の返り値はpthread_join
で指定したスレッドが終了するまで帰ってこない。(そのため無限ループになるとpthread_join
を呼び出した関数も終了できなくなる。)
言ってしまえば, この関数は非同期で処理されていたスレッドが合流するまで待つ関数である。
なお、pthread_join
をmain
に書いてあるが、これを他のスレッドから呼び出すことももちろん可能である。
しかし、そうなるとどこでスレッドが生成されてどこで合流するかがわかりにくくなるので、基本的にそのスレッドを生成したスレッドで待ち合わせをするべきである。
また、pthread_join
を呼ぶ前にスレッドが終了していてもすぐに帰ってくるだけで、問題は無い。
OSはスレッドの実行が終了した後もスレッドのコンテキスト(終了したか?戻り値は何か?)を保持し続けるためである。
ただし、pthread_join
を呼び出すとOSはそのコンテキストを破棄する。
そのため、pthread_join
で待った後に再度pthread_join
で待ってはいけない。
通常、このような二重待ちを避けるためにpthread_join
で一度待った後にはスレッドIDにNULL
を代入することが推奨されている。
二重joinを避ける改良