5. モデル
今までの章でスレッドの生成、同期、および条件変数の使用などを説明してきました。これらだけでも十分に機能するアプリケーションを作成できます。
スレッドを使用したアプリケーションの代表的な使用パターンモデルを実装した簡単なアプリケーションを作り、それをベースに説明していきます。
5.1 パイプラインモデル
前述したように一般的な業務アプリケーションでは時系列に処理を行っています。この時系列な処理は、ある処理のアウトプットが次の結果のインプットだったりします。
ある処理を行っている間、その処理以前に行っていた処理は何もしていません。そしてその処理以降の処理も、インプットが来るのをひたすら待っているだけです。
今回のアプリケーションは、処理ごとにスレッドを起動し、スレッドは自分の担当する処理をこなします。処理を終えたら次のスレッドに処理を引継ぎ、処理依頼が来るまでサスペンドします。
一般的にパイプライン処理と言われているもので、CPU等のプロセッサでよく使われているロジックです。
5.1.1 仕様
プロンプトから文字列を入力します。その入力値をデータとしてスレッドが順番に処理し、処理を終えると次のスレッドに引渡し、またそこで処理を行います。最後のスレッドが処理結果を出力します。
今回はあくまでサンプルなので、処理数は5個(よってスレッド数も5個)、実際の処理は入力値を画面出力しているだけです。
5.1.2 プログラム
200行程あるプログラムなので、ダウンロード形式にしました。プログラムをダウンロードして頂き、「pipe_test.c」をコンパイルし実行してください。引数は必要ありません。
5.1.3 分析
各スレッドは担当する処理を行うためのステージが用意されています。数値が入力されると、1個目のステージへデータが設定され、そのステージの担当のスレッドが起き、データを処理し、次のステージに結果を引き渡し、次のステージの担当のスレッドを起こし、サスペンドします。
パイプラインの利点は、ある処理に多くの時間が掛かっていても、その間他の処理を進められることです。
処理要求が1つしかない時は今までの時系列型アプリケーションと変わらない数値になるでしょう。しかし処理要求が複数且つ同時に大量に発生し、処理もDBを読んだりする様な比較的時間のかかる処理の場合、平行して処理を行える分、トータルの処理時間は短縮できると思われます。複数の処理を順番に処理していくようなアプリケーションに対して効率的なアルゴリズムと言えるでしょう。
5.2 ボス・ワーカーモデル
先の例と異なり、全スレッドに対し同じような処理を行わせたい場合があります。データ処理対象のスレッドは、処理対象のデータがあればそのデータを受け付けて処理します。無ければデータが投入されるまでサスペンドします。処理対象データの入れ物を監視し、データが入るまでサスペンドし、入ってきたら我先に動き出す、簡易版スレッドプールとも呼べるでしょう。
5.2.1 仕様
プロンプトからディレクトリを入力、配下の全ファイルを調査対象にし、同様にファイルを開いて特定文字列を探します。実行する際の引数は起動するスレッド数です。実行するとプロンプトが出てきます。入力値は、"(directory of file:string)"です。':'を区切り文字として使用しています。
| directory of file | ファイルかディレクトリを期待してます。 |
| string | そのファイル内に含まれる文字列です。ファイルを開いてstringを探します。見つかったら見つかった旨報告します。 |
/home/guest:int
例では「/home/guest」内の全ファイルに対し"int"文字があるか調査します。
5.2.2 プログラム
これも200行ちょっとあるプログラムなので、ダウンロードして頂き、「worker_test.c」をコンパイルし実行してください。引数が1つ必要で、その値は処理数(スレッド数)です。
5.2.3 分析
入力された文字列は処理対象用のデータとしてデータ管理リストに積み、以降はスレッドに処理させています。スレッドの方はデータを取得しデータの種類(ディレクトリかファイルかそれ以外か)によって動作が異なります。ディレクトリであればディレクトリを開き、ファイル名をデータ管理リストに次々積み、他スレッドに処理させていきます。ファイルであれば開いてから調査対象文字列を検索します。
このような処理を行う場合、再帰処理等で行うのが一般的でしょうが、今回はスレッドで実装しました。処理内容が単純でとにかく大量データをさばきたい場合に効率的なアルゴリズムと言えるでしょう。ただし、このままのプログラムでは出力結果がソートされていないので、出力に工夫が必要です。
5.3 所感
今回のサンプルは200行程度で小さいながらも、スレッドの動作および利点が比較的分かりやすいものと思います。mutexと条件変数はスレッドには必須なので、その使い方はちゃんと理解しておきたいです。逆にmutexと条件変数を理解し、使用に慣れさえすれば、それで十分にスレッドを使用できます。
以降の章はスレッドの中でも少々特殊な処理で、使用方法によってはやや実装依存な所もあります。
