LASSIC Media らしくメディア
プロセスとスレッドの違い|並行処理の基礎
LASSIC IT事業部|元請(プライムベンダー)としてシステム開発・検証を受託
システムの性能や安定性について話していると、「これはマルチプロセスで動かしている」「そこはスレッドで並列化した」といった言葉がよく登場します。プロセスとスレッドは、どちらもOSが管理する「処理を実行する単位」ですが、メモリの持ち方や独立性という点でまったく異なる性質のものです。この違いを理解しないまま並行処理の設計を進めると、想定外の不具合や性能上のボトルネックにつながることも少なくありません。
本記事では、プロセスとスレッドという二つの実行単位の違いを、仕組み・メモリ共有と安定性・生成コストとコンテキストスイッチ・使い分けの判断軸という観点から整理します。特定のプログラミング言語や製品には深入りせず、発注担当者・PM・設計者が押さえておきたい「考え方の違い」に焦点を当てて解説します。
この記事のポイント
- プロセスはOSから独立したメモリ空間を割り当てられる実行単位、スレッドは同じプロセス内でメモリ空間を共有する軽量な実行単位という違いがあります。
- スレッドはメモリを共有する分、生成やデータのやり取りが軽快な一方、一つのスレッドの不具合が同じプロセス内の他スレッドに及ぶ恐れがあり、データ競合への配慮も欠かせません。
- 障害の影響範囲を独立させたいのか、リソースを効率よく共有したいのかという観点で、マルチプロセスとマルチスレッドを使い分ける判断が求められます。
目次
プロセスとは(独立したメモリ空間を持つ実行単位)
プロセスとは、OSがプログラムを実行する際に割り当てる、独立したメモリ空間を持つ実行単位です。あるプログラムが起動すると、OSはそのプログラム専用のメモリ領域を確保し、他のプログラムのメモリ領域とは隔てられた状態で実行を開始します。
身近な例:起動しているアプリケーション
パソコンで複数のアプリケーションを同時に開いているとき、それぞれのアプリケーションは基本的に別々のプロセスとして動いています。一方のアプリケーションが不具合を起こして強制終了しても、他のアプリケーションがそのまま動き続けられるのは、メモリ空間が互いに独立しているためです。
独立していることの意味
プロセスが独立したメモリ空間を持つということは、あるプロセスが持つ変数やデータに、別のプロセスが直接アクセスできないということでもあります。プロセス同士でデータをやり取りしたい場合は、OSが提供するプロセス間通信(IPC)という仕組みを介する必要があり、この隔たりが堅牢性と引き換えに一定のコストを生む要因になります。
スレッドとは(メモリを共有する軽量な実行単位)
スレッドとは、一つのプロセスの内部で動く、より軽量な実行単位です。一つのプロセスは一つ以上のスレッドを持ち、同じプロセスに属する複数のスレッドは、そのプロセスに割り当てられたメモリ空間(ヒープ領域やグローバル変数など)を共有します。
身近な例:一つのアプリケーション内の複数の処理
ファイルの保存中も画面の操作を受け付け続けるアプリケーションでは、画面表示を担当するスレッドと、保存処理を担当するスレッドが、同じプロセスの中で並行して動いていることがあります。両者は同じデータ(開いているファイルの内容など)を参照しながら、それぞれの役割を並行してこなしているわけです。
共有していることの意味
スレッド同士が同じメモリ空間を共有しているということは、一方のスレッドが書き換えたデータを、もう一方のスレッドがそのまま参照できるということです。プロセス間通信のような仲介の仕組みを必要とせず、直接データをやり取りできる手軽さがある一方、複数のスレッドが同じデータへ同時にアクセスすると、想定していない順序で処理が進んでしまう「データ競合」が起こり得る点には注意が必要です。
両者の違い:対比表と構造図
プロセスとスレッドは、どちらも「OSが管理する実行の単位」という点では共通していますが、メモリの持ち方という前提がまったく異なります。主な観点を次の表に整理します。
| 観点 | プロセス | スレッド |
|---|---|---|
| メモリ空間 | 独立した専用の領域を持つ | 同じプロセス内で共有する |
| データのやり取り | プロセス間通信(IPC)が必要 | 共有メモリを介して直接やり取り可能 |
| 生成のコスト | メモリ確保などがあり比較的重い | 同じメモリ空間を使うため比較的軽い |
| 切り替えのコスト | メモリ空間の切り替えを伴い重くなりやすい | 同一プロセス内のため比較的軽くて済みやすい |
| 障害発生時の影響 | 他プロセスへ影響しにくい | 同じプロセス内の他スレッドに影響することがある |
| 注意すべき点 | 通信の仕組みや連携の複雑さ | データ競合と排他制御の設計 |
対比表からわかるとおり、プロセスとスレッドはどちらか一方が常に優れているという関係ではなく、独立性を優先するか、リソースの共有と軽快さを優先するかというトレードオフの違いです。次の図で、複数の処理を並行させる場合の構造の違いを確認しておきましょう。
メモリ共有と安定性の観点
プロセスとスレッドの違いが最も実務に効いてくるのが、メモリの共有と安定性の観点です。
障害の影響範囲
プロセスは独立したメモリ空間を持つため、あるプロセスが異常終了しても、そのメモリ領域はOSによって回収され、他のプロセスの実行にはほとんど影響しません。一方、同じプロセスに属する複数のスレッドは、一つのメモリ空間を共有しているため、あるスレッドが不正なメモリアクセスなどを起こしてプロセス自体が異常終了した場合、同じプロセス内の他のすべてのスレッドも巻き込まれて停止することになります。
データ競合という固有の課題
スレッドが共有するメモリに対して、複数のスレッドが同時に読み書きを行うと、処理の順序によって結果が変わってしまう「データ競合」という問題が起こり得ます。これを防ぐためには、同時に一つのスレッドしかアクセスできないようにする排他制御(ロックなど)の仕組みが必要です。プロセスにはメモリ空間が隔てられているためこの種の競合は基本的に発生しませんが、その代わりにデータをやり取りするための通信の仕組みを別途用意する必要があります。
安定性を優先する設計
障害の影響を最小限に抑えたい機能や、他の処理から切り離して安定して動かしたい処理については、プロセスとして分離する設計が選ばれやすい傾向にあります。反対に、頻繁にデータをやり取りしながら軽快に並行処理を進めたい場面では、スレッドによる共有が向いていることが多いでしょう。
生成コストとコンテキストスイッチ
プロセスとスレッドは、生成にかかるコストや、複数の実行単位を切り替える際のオーバーヘッド(コンテキストスイッチ)の大きさも異なります。
生成にかかるコスト
新しいプロセスを生成する際、OSは専用のメモリ空間を確保し、初期化するといった作業を行うため、一定の時間とメモリの負荷がかかります。これに対して新しいスレッドを生成する場合は、すでに存在するプロセスのメモリ空間をそのまま利用できるため、確保する必要があるのは主にスレッド固有のスタック領域程度にとどまり、生成の負荷は比較的軽く済む傾向があります。
コンテキストスイッチの重さ
CPUが複数の実行単位を切り替えながら処理を進める際、切り替え先のメモリ空間の情報も含めて入れ替える必要があるプロセス間の切り替えは、同じメモリ空間を使い続けるスレッド間の切り替えと比べて、オーバーヘッドが大きくなりやすいという特徴があります。多数の実行単位を細かく切り替えながら並行処理を行いたい場合、この違いが全体の処理性能に影響を与えることもあります。
コストと安定性のトレードオフ
生成や切り替えの軽さだけを見ればスレッドに分があるように見えますが、これは前述のとおり、障害の影響範囲やデータ競合のリスクと引き換えになっている面があります。処理の性能だけでなく、安定性や保守のしやすさも含めて総合的に判断することが重要です。
使い分けの判断軸(マルチプロセス vs マルチスレッド)
プロセスとスレッドのどちらに寄せて並行処理を設計するべきかは、次のような判断軸を確認すると整理しやすくなります。
- 障害の分離――一部の処理が異常終了した際に、他の処理への影響をどこまで抑えたいか
- データの共有頻度――複数の処理が同じデータを頻繁にやり取りする必要があるか
- 生成・切り替えの頻度――短時間で何度も実行単位を生成したり切り替えたりする処理か
- 実装・運用の負荷――排他制御の設計やデバッグの複雑さをどこまで許容できるか
- リソースの利用効率――限られたメモリやCPUをどう配分したいか
マルチプロセスが向く場面
複数の独立したジョブを並行して処理するバッチ処理や、一部の異常終了が全体へ波及することを避けたい基幹系の処理では、プロセスとして分離する設計が選ばれやすくなります。それぞれのジョブが互いに干渉せず、一つが失敗しても他のジョブへ影響しにくいという特徴が生きる場面です。
マルチスレッドが向く場面
一つの画面の中で複数の作業を並行して進めたい場合や、同じデータを頻繁に参照しながら細かい処理を並行させたい場合には、共有メモリを活かせるスレッドによる並行処理が向いています。データのやり取りのたびに通信の仕組みを経由する必要がなく、軽快に連携できる点が強みになるでしょう。
組み合わせというアプローチ
一つのシステムであっても、すべての処理を同じ方針で統一する必要はありません。重要度の高い処理は独立したプロセスとして分離しつつ、そのプロセス内部の細かい並行処理はスレッドで実現するというように、性質ごとに組み合わせて設計するアプローチは実務でも珍しくありません。
設計・発注時の確認点
並行処理の設計を発注する際は、次のような点をあらかじめ確認しておくと、後の手戻りを抑えやすくなります。
- どの処理を独立したプロセスとして分離し、どの処理をスレッドで並行させるかの方針が整理されているか
- スレッドで共有するデータについて、排他制御の設計方針が明確になっているか
- プロセス間で通信が必要な箇所について、その仕組みと想定される負荷が説明されているか
- 一部の処理が異常終了した際に、システム全体への影響がどこまで抑えられる設計かが確認されているか
- 並行処理に関するデバッグや監視の方法が、開発・運用のフェーズであらかじめ計画されているか
実行単位をプロセスにするかスレッドにするかという判断は、システムの安定性や保守性の土台に関わる部分であり、実装が進んだ後に方針を切り替えるとなると、設計の見直しが広範囲に及びやすい部分です。発注段階でこうした確認点を共有しておくことが、期待とのズレを防ぐことにつながるでしょう。
まとめ:実行単位の違いは障害設計の前提になる
本記事では、プロセスとスレッドという二つの実行単位の違いについて、仕組み・メモリ共有と安定性・生成コストとコンテキストスイッチ・使い分けの観点から整理しました。プロセスは独立したメモリ空間を持つ実行単位、スレッドは同じプロセス内でメモリ空間を共有する軽量な実行単位であり、独立性と共有という点で性質が異なります。
設計にあたっては、障害の分離・データの共有頻度・生成や切り替えの頻度・実装や運用の負荷・リソースの利用効率といった判断軸を確認し、処理の性質に応じてマルチプロセスとマルチスレッドを使い分ける、あるいは組み合わせることが、無理のない並行処理の設計につながるでしょう。
よくある質問
スレッドの方が速いのですか。
一概にそうとは言えません。スレッドは共有メモリを介して軽快にデータをやり取りできる大きな特徴を持ちますが、データ競合を防ぐための排他制御が処理の待ち時間を生むこともあります。独立性を優先したい処理ではプロセスによる分離の方が結果的に安定して動く場合もあり、どちらか一方が常に速いという関係ではないと捉えるのが適切です。
プロセスとスレッド、どちらを選ぶべきですか。
障害の分離を優先したいか、リソースの共有と軽快さを優先したいかという観点で判断するとよいでしょう。一部の異常終了を他の処理に波及させたくない場合はプロセスによる分離、同じデータを頻繁に参照しながら並行処理を進めたい場合はスレッドの活用が向いています。両者を組み合わせて設計するケースも珍しくありません。
データ競合とは具体的にどのような問題ですか。
複数のスレッドが同じメモリ上のデータへ同時に読み書きを行った際、処理の実行順序によって結果が変わってしまう問題です。想定していない順序で処理が進むと、データの整合性が崩れることがあります。同時に一つのスレッドしかアクセスできないよう制御する排他制御の仕組みによって、こうした問題を防ぎます。
プロセス間でデータを共有したい場合はどうすればよいですか。
プロセスはメモリ空間が独立しているため、直接データを共有することはできません。共有したいデータがある場合は、OSが提供するプロセス間通信(IPC)の仕組みを使い、ファイルや専用の通信経路を介してデータをやり取りする設計が一般的です。
一つのプロセスにスレッドはいくつまで作れますか。
OSやハードウェアの制約によって上限は変わりますが、スレッドを増やせば増やすほど処理が速くなるとは限りません。スレッドが増えるほど切り替えの回数やデータ競合の管理も複雑になりやすいため、処理の性質に見合った数へ設計することが実務では重要です。
既存のマルチスレッド処理をマルチプロセスに作り直す必要はありますか。
必ずしもその必要はありません。すでに安定して稼働している仕組みを無理に作り直すと、かえって複雑になる場合もあります。障害の影響範囲や保守性が課題になっている箇所から優先的に見直すなど、段階的な検討が現実的でしょう。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:IPA(情報処理推進機構)基本情報技術者試験シラバスにおけるプロセス・スレッドに関する解説(https://www.ipa.go.jp/shiken/syllabus/index.html)