猿にはわからないスレッドの話

「猿でもわかるスレッド講座」ぐらい言えればいいのですがー
まぁ、講座できるほど説明がうまいわけでもないし、詳しいことがわかるわけでもないのでー


「猿にはわからないスレッドの話」ということでw


スレッドを作るのは簡単です、書式を勉強すれば誰でも作り出せます。
難しいというか、ハマりやすいのは、書式は問題ないのに、同期に失敗してバグを生み出すことです。
コレは「共有されているものに、どれぐらい注意できるか?」という単純な話でもあります。
通常のプログラムとマルチスレッドの違いは、プログラムが実行されている流れが1つだけなのか、複数あるのかです。
どこにも共有しているものがなければ、通常のプログラムとなにも変わりません。
複数の実行型を起動している状態と同じですね。(マルチプロセスでの動作ですね。)
お互いに共有するものが無ければ相手のことなど考えなくていいわけです。


じゃー共有するものがあった場合はどうかと考えるとー
そう、例えばファイルに対して書き込みをするプログラムが2つあったとします。
どちらか1つだけが動作している場合は、なにも問題はありません。
この2つのプログラムが同時に動作していても、別々のファイルを扱っているなら問題ありません。
問題が発生するのは、同時に同じファイルを扱う場合です。
対象のファイルがどうなってしまうのか・・・タイミングやプログラムのつくりで様々な結果になりますね。


マルチスレッドってのも同じことです、マルチプロセスと同じことが発生します。
問題は、マルチプロセスが共有しているものは比較的わかりやすいが、マルチスレッドが共有しているものは判りにくいことです。
まぁ、細かいものが共有されているので、見落としやすいってことですね。
より具体的に言えば、「変数」が共有されているからです。
ファイルなどと違って「共有している」という意識が薄くなりやすいんですねぇ。


同期という点でもう1つ。
スレッドの扱いでもっとも難しいと思うのは、スレッドの終了です。
スレッドは開始することよりも終了させるほうが難しいです。
これもマルチプロセスで考えると想像しやすいと思います。
起動したのはいいが、途中で停止(終了)させたい場合・・・いろいろなパターンがありますね。
もちろんプロセスを殺して強制終了させる方法もありますが・・・通常最後の手段になりますよねぇ。


スレッドの終了待ちとしてWaitForMultipleObjectsでタイムアウト指定ができたりしますが・・・
どう処理しているのかで、スレッドに対する理解力がわかると思います。
エラーの1つだと見立てて、そのまま終了してしまうようなコード・・・ありませんか?
CloseHandleして綺麗に終わった気になってませんか?


タイムアウト=処理は継続中


エラーではないのです。
タイムアウトとして終了したいなら、スレッド側に外部からスレッドを停止させる仕組みを入れるべきです。
ちなみに、スレッド実行中でもCloseHandleは正常終了します。
ハンドルは閉じられますが、スレッドはそのまま継続するんですねぇ。
なんか、あまりにも堂々とタイムアウト後にCloseHandleして終了しているサンプルをみてー
「あれ?スレッドも強制終了するのかな?」とか思ってしまいましたが、そんなことは当たり前のようになかったですw


もちろん、プロセスの終了時にはスレッドも強制終了するんですが・・・
mallocしてfreeしないってなものとは全然違うわけで・・・
ファイル操作するようなスレッドとかだと結構泣けることになりそうですねぇ。
スレッドを扱う場合は、そのスレッドがいつ終了するのかということにも注意しましょうって話です。


PS.
CloseHandleで閉じたハンドル変数にNULLを代入しないと駄目ってな話・・・ガセだと思うんだけど、どうなんだろう?
C#とかのガベージコレクションのイメージなんですかねぇ。
少なくともC++でNULLを代入しておかないといけない理由がみつからない。
あるとしたらハンドル変数がNULLなら、ハンドルを使用していないという設計で作成しているような場合だと思うんだけど・・・
ガセだよーとか、こうかもーみたいな意見があればコメント欄で教えてくだされー。
まぁ、ソレ書いた本人が守ってないようなものだからなぁw