スレッドを調べまわって分かったことをメモ


こうですか?分かりません!><


WIN32のみのお話です。
スレッドって結構実装依存なのね…。

先にまとめ

CreateThread

  • C++では無くCの関数。
  • そのまま使うとメモリリークを起こすので、マルチスレッドなC++では使ってはいけない
    • 古いC++のメソッドは、グローバル変数を使ってたり何なりでマルチスレッドに弱いのが多い
  • メモリの解放の処理をラップした、beginthreadと、_beginthreadexを使うべし
  • MFCの場合は、AfxBeginThreadを使うべきらしい

_beginthreadと、_beginthreadex

そもそもの違いは?
  _beginthread _beginthreadex
呼出規約 __cdecl or __clrcall __stdcall or __clrcall
Handleのクローズ 終わったら勝手に閉じる CloseHandleで明示的に閉じる必要あり
エラー時の戻り値 -1 0
停止した状態でスレッドを生成 ×
スレッド識別子 ×
子プロセスへの継承 ×
どっちが良いの?

オフィシャルとしては、_beginthreadexを推奨

_beginthread よりも _beginthreadex を使用した方が安全です。
_beginthread によって生成されたスレッドの終了が早すぎると、_beginthread の呼び出し元に返されるハンドルが無効になる可能性や、別のスレッドを指す可能性があります。
しかし、_beginthreadex から返されるハンドルは _beginthreadex の呼び出し元で閉じられる必要があるため、_beginthreadex がエラーを返さなかった場合にはハンドルが有効であることが保証されます。

MSDN:_beginthread、_beginthreadex (CRT)

  • _beginthreadは呼出先のメソッドが終了すると、勝手にハンドルを閉じます
    • 呼出直後に終了するようなメソッドを呼で、ハンドルがあること前提の処理を親側に入れると危険
      • 場合によっては、別のスレッドに影響が及ぶらしいです。
  • _beginthreadexは明示的にハンドルをCloseしなければならないので、忘れるとそれはそれでメモリリークの危険

呼出し規約について

  • _beginthreadは、__cdecl
  • _beginthreadexは、__stdcall
__cdecl
  • 簡単に言えば、staticなメソッド
__stdcall
  • staticだが、Windows APIの呼び出し規約に基づいたメソッド。
  • 具体的には宣言時に関数名の前にWINAPIをつける。
int WINAPI func( void );
  • __cdeclより早いらしい。


詳しくはこちらを参照→二流プログラマの三流な日常: 関数呼び出しの内部を理解する(2)

わかんなかったこと

  • _beginthreadの存在理由がいまいち分からず。
    • 勝手にハンドルを閉じてくれるのは便利ともいえるけど…。
    • スレッド作りっぱなしで、その後、ハンドルを使って色々する気が無いなら、_beginthreadでも良いってこと?

その他

参考リンク