第18講 マルチスレッドプログラミング 
第3話 新たなスレッドを起動するには?

スレッドを新たに起動する方法は、C言語だけでも3つあり、
C++やVC++にも多数ありますので、おそらく全部で10を超える方法があるのではないでしょうか。
私が知っている方法は、このうち4つほどですが、1つだけ紹介していきます。
残りの3つは、Windows上で動くWindowsソフトであり、C言語ではないからです。

その方法とは、
_beginthread関数を使用する方法です。
_beginthread関数は、引数を3つもっています。
_beginthread(関数名、新規スレッドのスタック サイズまたは 0、新規スレッドに渡される引数リストまたは NULL)
この中で、新規スレッドのスタック サイズまたは 0、新規スレッドに渡される引数リストまたは NULLの部分が?でしょうが、
そこは、0とNULLしておくものだと思ってください。
NULLはデータがないことです。
ですから、基本的に_beginthread関数は
_beginthread(f,0,NULL)と使用すると考えてください。
_beginthread関数を使用するには、process.hをインクルードしておく必要があります。

具体例がないとわかりにくいと思いますので、
新規プロジェクトから次のようにコーティングして下さい。
#include<iostream>
#include<process.h>
using namespace std;
void f(void *a);
void g(void *a);
int main(){
  _beginthread(f,0,NULL); //新しいスレッドを起動して、そのスレッド上で関数fを働かせなさいの命令
  _beginthread(g,0,NULL); //新しいスレッドを起動して、そのスレッド上で関数gを働かせなさいの命令
  cout<<"a"<<endl;
}
void f(void *a){
  cout<<"b"<<endl;
}
void g(void *a){
  cout<<"c"<<endl;
}
void *aの部分が非常に気になるでしょうが、
今のところこれは必要なお呪いだと思ってください。
注釈文に書いてありますが、
_beginthread(f,0,NULL);
で新しいスレッドを起動して、そのスレッド上から関数fを呼び出しなさいという命令を遂行しています。
_beginthread(g,0,NULL);
は同様に新たにスレッドを起動してそのスレッド上に関数gを展開しなさいということです。
C++
_beginthread(f,0,NULL);によって図の上のスレッドが起動して、そのスレッド上で関数fが展開します。
_beginthread(g,0,NULL);によって図の下のスレッドが起動して、そのスレッド上で関数gが働きます。

さて、実行結果ですが・・・
c++c言語入門初心者基礎初歩マルチスレッド並列処理
と実行する度に結果が変わってきます。
どうしてこのような奇妙な振る舞いが起きてしまうのでしょうか。
理由は、3つの処理が同時に並列に処理されているからです。
3つのスレッドがそれぞれ独自に同時に仕事をしているのです。
3スレッドが同時に働く結果、
その時々によって結果が違ってしまうのです。
ルートスレッドの方が一番先に結果を出したり、
fを展開しているスレッドが一番先に結果と出したり、
gを展開しているスレッドが一番先に結果を出したりするのです。
例えば、直列処理の結果は何故引き起こされるのでしょうか。
cout<<"b"<<endl;
ですからすぐに改行されるはずです。
fがbをコンソールに打ち出し次に改行しようとしているときに、
gのcのアウトプットが割り込んでしまったのです。
そして、fとgが改行しようとしている最中に、
ルートのaのアウトプットが割り込んでしまったのです。
そうすると3つのスレッドの改行がまだ残っていて、
それらが続いて起きたためにスレッドの起動となってしまったのです。
実際に何回も粘り強く実験していくと入門となる場合もあります。

結果が時に応じて変わることが、
マルチスレッド=並列処理が成功しているを示しています。

では、次話では各スレッドに時間のかかる処理をさせてCPU使用率が100%になっていることを確認しましょう。
時間のかかる処理なら何でもよいわけですから、例えば1から100000000まで素数探索をさせてみましょう。

これを4スレッドで探索するには、2,3,5までプログラム上に入れてしまい、
7以上の奇数(素数は2以外はすべて奇数)について、
5で割ると1余るタイプ
5で割ると2余るタイプ
5で割ると3余るタイプ
5で割ると4余るタイプ
の4つのタイプに分けて、それぞれのスレッドで探索させれば実現可能です。

初心者
(これは1から1000までの場合の探索結果)

さて、皆さんどうしたらよいでしょうか。

第2話へ 第4話へ

戻る

C言語 C++講義第1部へ
VB講義へ
VB講義基礎へ

vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)