C/C++マルチスレッド学習の心得まとめ


マルチスレッドのプログラミングを学ぶ前に、プロセスとスレッドの関係を知っておいたほうがいいと思います。そして、スレッドの働き方を勉強している間に、マルチスレッドの小さいプログラムを書きます。マルチスレッドの学習に大きな助けがあります。そうでなければ、理論だけがとても抽象的です。マルチスレッドのプログラミングを学ぶ前に、スレッド関数とは何かを知っておかなければなりません。スレッド関数はもう一つのスレッドの入口関数です。デフォルトでは私たちが書いたコードはスレッドだけです。このスレッドの入口関数はメーン関数です。これはシステムのデフォルトです。私たちが作成したもう一つのスレッドも関数として入ります。この関数はスレッド関数といいます。C/C++では、「実行期間ライブラリ」関数を呼び出すことができます。Beginnthreadex(…)は、スレッドを作成します。Beginnthreadex(...)関数は6つのパラメータを受け入れています。このうち、3番目のパラメータは、スレッドの入口関数に入るアドレス(すなわち、スレッド関数名に入ってきます。+&OK)を要求しています。他の各パラメータの意味はmsdnやインターネットで調べられます。入門すると、残りのパラメータは全部0になります。Begintthreadex(...)関数はハンドルを返します。新しいスレッドのハンドルです。入ってきたスレッド関数には要求があります。スレッド関数はunsigned_u()に返さなければなりません。stdcalタイプで、void*型のパラメータを受け入れると、関数の内容は自分で決められます。まずマルチスレッドの簡単なコードを使います。

#include<windows.h>
#include<process.h>
#include<iostream>
using namespace std;
bool stop;
unsigned Counter;
unsigned __stdcall thread(void*)
{
cout <<"In second thread..." <<endl;
while (!stop){
Sleep(200);
cout <<Counter++ <<" " <<flush;
}
//_endthreadex(0);
return 0;
}
int main()
{
HANDLE hThread;
unsigned int threadID;
stop = false;
cout <<"Creating second thread..." <<endl;
// Create the second thread.
hThread = (HANDLE)_beginthreadex(NULL, 0, &thread, NULL, 0, &threadID);
// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
//WaitForSingleObject(hThread, INFINITE);
system("pause");
stop = true;
//cin >>stop;
cout <<"Counter is-> " <<Counter <<endl;
// Destroy the thread object.
CloseHandle(hThread);
system("pause");
return 0;
}
コードは正しいです。Visual C++6.0にコピーして貼り付けて、コンパイルして実行できます。しかし、_を発見します。Beginnthreadex(...)関数が定義されていないコンパイルエラーの原因は、私たちのvisual c++6.0のデフォルトはシングルスレッドモードでプログラムされています。マルチスレッドプログラムが必要なら、コンパイラの「実行期間ライブラリ」を変換してください。方法は簡単です。Project-->Settings-->C/C++の中からCategoryのCode nerationを選択します。そしてUse run-time libraryの中からMultithreadの中の一つを選んでください。ここでコンパイルすれば通ります。この例の関数があって、今は入門しましたよね。でもこれ以外にも基礎知識がたくさんあります。何回か<windowsコアプログラミング(第四版)>の第6章を読んでください。実際には、異なるコンパイル環境の下で、_Beginnthreadex(...)関数には異なる名前がありますが、それらはすべてwindows関数CreateThread(...)のパッケージです。CreateThread(...)関数は新しいスレッド関数を作成するために使用されます。CreateThread(...)関数は同様に6つのパラメータを受け入れます。Beginnthreadex(...)の関数では、スタックメモリの申請などの安全な処理が行われています。CreateThread関数で新しいスレッドを作成することができますが、強く推奨されています。Beginnthreadex(...)関数は、CreateThread関数に対して<windowsコアプログラミング(第4版)>第6章でよく説明されています。スレッドのタスクが終了すると、終了する時に、スレッド関数が戻ります。2._を呼び出してendthreadex()またはExit Thread()関数は、スレッドが自分でキャンセルされます。3.同じプロセスまたは他のプロセスのスレッドがTerminate Thread()関数を呼び出します。4.スレッドを含むプロセスの実行を終了します。(この方法は避けるべきです。)その入口関数の返却文(すなわち、return)を通じてスレッドを終了した方がいいです。また、C/C++'の運転期間ライブラリ'関数_を呼び出してもいいです。endthreadex()関数が終了し、終了する2つの方法があります。同様の強制終了です。スレッド関数の戻り文を使ってスレッドを終了したほうがいいです。このようにしてこそ、スレッドのプロセッサリソースとメモリリソースを安全に回収することができます。実際には、_endthreadex()関数と_Beginnthreadex(...)の関数は同じです。Windows関数ExitThreadをカプセル化しています。強制的にスレッドを終了したいなら、強く呼びかけます。endthreadex()関数は、システムのリソースを安全に回収することができます。Beginnthreadex(…)関数と_endthreadex()関数は<windowsコアプログラミング(第4版)>第6章でよく分析されています。同時に二つの_もあります。beginnthread(…)と_endthread()運行期間ライブラリ関数についても説明があります。ウィンドウズは現在のプロセスまたはスレッドのハンドルを獲得するためにいくつかのライブラリ関数を提供しています。例えば、HANDLE GetCurentProcess()関数は現在のプロセスのハンドルに戻ります。HANDLE GetCurentThread()関数は現在のスレッドのハンドルに戻りますが、これらのハンドルはすべて「疑似ハンドル」です。すなわち、本プロセスと本スレッド内のみで利用できます。使用を伝えてはいけません。外部で他のスレッドやプロセスのハンドルを使用すると、DuplicteHandle(...)関数で他のプロセスやスレッドの「実文」が得られます。この関数は7つのパラメータを受け取ります。具体的な使い方はmsdnとネットワークを調べられます。注意してください。DupliccateHandle(...)関数で得られたハンドルを使用した後、Close Handle()関数を使ってハンドルを閉じる必要があります。