次の方法で共有


15.5 | スレッド操作指針

災難は避けたいものです。災難はスレッド操作時にも起こります。このため、スレッドを使用する場面とタイミングを考える必要があります。ここでは、スレッドを使用すべきシナリオと、複数スレッドの使用を避けるべきシナリオを紹介します。アプリケーション開発時の参考になれば幸いです。

15.5.1 | スレッドを使用すべきシナリオ

後ほど詳しく説明しますが、同時処理、設計の簡素化、CPU の有効活用などの改善を考える必要がある場面では、スレッドを使用すべきでしょう。

■■ 同時処理の改善

一般的には、アプリケーション内で一度に複数の処理を行う必要があります。たとえば、私はかつて銀行のドキュメント検索システムを開発したことがありました。そのシステムでは、光ディスク専用装置に格納されている光ディスクにアクセスして必要なデータを取り出していました。ご想像のように、そのようなアプリケーションは大量のデータを処理しなければなりません。光ディスク専用装置にドライブが 1 つしかなく、その 1 つのドライブで 50 個のプラッタを駆動しているとしましょう。データ量は数ギガです。ディスクを挿入して、要求されたドキュメントを検索するのに、5 秒から 10 秒かかったとしたらどうでしょう。アプリケーションが自分の処理をしている間、ユーザーからの入力をブロックしていたら生産性は向上しません。私は、先のアプリケーション開発時に、データ取出しなどの物理的な動作を伴う処理は、独立したスレッドを生成して対処しました。これにより、ユーザーへの影響はほとんどありませんでした。作成されたスレッドは、ドキュメントのロードが完了した時点で、メインスレッドにその旨を通知するように実装しました。これは、相互に独立した 2 つのスレッドを応用した同時処理(ドキュメントロードと UI 対応)の優れた例の 1 つといえるでしょう。

■■ 設計の簡素化

複雑なシステムの設計を簡素化する一般的な方法は、キューと非同期処理を採用することです。このようなシステムでは、システム内で発生するいろいろなイベントを処理するためのキューを設定することになります。メソッドを直接呼び出すのではなく、作成されたオブジェクトはキューに置かれ、必要な時点で処理されるようになります。サーバープログラムは複数のスレッドを起動し、キューにメッセージが入ってくることを監視します。この単純なシステムは、信頼性、堅牢性、および拡張性のいずれの点でも優れた設計といえます。

■■ CPU の有効活用

アプリケーションによっては、タイムスライスが与えられていても、重要な処理を行っていないことがあります。先ほど紹介した私が開発したドキュメント検索システムでは、光ディスク専用装置にアクセスする専用のスレッドを 1 つ用意していました。当然、待ち時間が発生しますが、それはハードウェアの問題であり、CPU を占有しているわけではありません。これと似たような場面には、ドキュメントの印刷やハードディスクと CD-ROM ドライブへのアクセスなどがあります。いずれの場合も、CPU は有効活用されていません。このため、対策としてはバックグラウンドで動作するスレッドにしてしまうとよいでしょう。

5.5.2 | スレッドを使用すべきでないシナリオ

スレッドを初めて使用できるようになったプログラマは、すべてのアプリケーション内でスレッドを使用しようとします。これは、はっきり言ってよくある間違いです。スレッドを使用すると、それに関係する問題も発生します。すべてのプログラミング手段にいえることですが、必要なときにのみスレッドを使用するべきなのです。次のような場面では、複数スレッドの使用を可能な限り避けた方がよいでしょう。

■■ 大きすぎるコスト

「15.4 スレッドの安全性と同期」で述べたように、マルチスレッドアプリケーションの設計コストは高くなります。スレッドの安全性を確保できたとしても、効果がなければ意味がありません。開発時間と設計コストを考慮し、複数のスレッドを使用するかどうかを決定すべきです。

■■ 不確かなメリット

マルチスレッドアプリケーションを開発した経験がない方は驚くかもしれませんが、スレッド作成とスケジューリングには膨大な CPU オーバーヘッドがかかります。このため、結果として、シングルスレッドアプリケーションの方が高速に動作するようなこともあるのです。すべては処理内容であり、それぞれに独立した処理をスレッドとして分割しているかにかかっています。たとえば、3 個のファイルをハードディスクから読み出すとしましょう。この場合、3 個のファイルの読み出し処理それぞれに、合計 3 個のスレッドを作成してもメリットはまったくありません。理由は簡単です。個々のスレッドは、同一のハードディスクを使用することになるからです。このため、アプリケーションを作成する場合には、シングルスレッドとマルチスレッドの両バージョンを用意し、動作を評価することが大切です。きちんと評価をしたうえで、作業を開始するようにするのです。このような姿勢で臨めば、時間も設計コストも無駄になることはありません。稼動した後で、パフォーマンスの低さを指摘されるようなこともありません。

■■ 不明確な理由

マルチスレッドを使用することは、何も決められた規則ではありません。マルチスレッドアプリケーション開発は複雑な作業になりますから、明確な理由がない限り、シングルスレッドアプリケーションを開発することを考えるべきです。むしろ、これは基本原則である、と考えておくとよいでしょう。

まとめ

マルチスレッドを使用すると、アプリケーションが行う各処理を分割することができます。分割された処理は相互に独立して実行されるため、プロセッサを効率よく共有できるようになります。しかし、アプリケーション内で複数のスレッドを使用することは、最良の選択ではないという認識も必要です。設計を間違えると、アプリケーションの動作が低下してしまいます。C# のスレッド管理と作成機能は、System.Threading.Thread クラスに実装されています。スレッドを作成し、それを使用する場合、スレッドの安全性に注意することが大切です。スレッドの安全性というのは、オブジェクトのメンバが常に有効な値を保持していることです。複数のスレッドから同時にアクセスされたときも、その値は有効となっている必要があります。マルチスレッドプログラミングテクニックを学ぶときには、プログラミング構文と共に、使用する適切なシナリオ(同時処理の向上、設計の簡素化、CPU の有効活用)を理解できる能力を身に付けることも重要です。