プログラムが実行されるとき、OSはプロセスとスレッドという2つの単位で動きを管理します。
これらの違いを理解すると、性能や安定性、設計判断が明確になります。
本記事では基礎からOSの動作、実例、設計の注意点までを初心者向けに整理して解説します。
比喩や表で直感的に捉え、現場ですぐ活用できる判断軸を得られます。
プロセスとスレッドの違いとは?

プロセスはアプリ全体の入れ物で、スレッドはその中で動く作業員のような存在です。
建物(プロセス)が別なら中の人(スレッド)同士は直接行き来できず、通路(IPC)が必要です。
同じ建物の部屋(スレッド)なら資料(メモリ)は共有できますが、取り合いにならないように鍵(排他制御)が必要になります。
次の表は、主要な違いをひと目で整理したものです。
観点 | プロセス | スレッド |
---|---|---|
アドレス空間 | 独立している | 同一プロセス内で共有する |
スタック | 各プロセス内のスレッドごとに別 | 各スレッドが個別に持つ |
作成・破棄コスト | 相対的に大きい | 相対的に小さい |
通信 | IPC(パイプ、ソケット、共有メモリなど)が必要 | 共有メモリに直接アクセス可能(同期が必要) |
障害の影響範囲 | 他プロセスへ波及しにくい | 同一プロセス全体に波及しやすい |
スケジューリング単位 | コンテナとしての単位 | 多くのOSで実行単位 |
代表用途 | サービス分離、セキュリティ境界、堅牢性 | 応答性向上、細粒度の並列化 |
プロセスの定義と役割
プロセスは、実行中のプログラムの1インスタンスで、独立したアドレス空間、ファイルディスクリプタ、環境変数、セキュリティコンテキストなどを持ちます。
OSはプロセス間でメモリを原則分離し、1つが暴走しても他に直接影響しにくいように守ります。
サービスを分けたいとき、権限やリソースを分離したいとき、障害を閉じ込めたいときに適しています。
典型的な役割
独立性が高いため、マイクロサービスやプラグイン分離、ワーカー群のスケールアウトなど、失敗を局所化したい場面で活躍します。
また、OSの機能(cgroupsや権限)と組み合わせることで、CPUやメモリの使用量を制限することもできます。
スレッドの定義と役割
スレッドは、同一プロセス内で動作する軽量な実行単位です。
各スレッドは自分のレジスタ状態とスタックを持ち、ヒープなどのプロセス共有メモリへは全スレッドからアクセスできます。
I/O待ちと計算を並行実行したり、UIの応答性を維持したり、データの並列処理を行うときに有効です。
典型的な役割
短時間で多数の作業を切り替える、共通のデータ構造を共有しながら並行に処理を進める、といった用途に向いています。
反面、共有メモリを扱うためレースコンディションやデッドロックへの注意が不可欠です。
メモリ共有とリソースの境界
プロセス間ではアドレス空間が独立しているため、直接相手のメモリを書き換えられません。
代わりにIPCを用います。
一方、同一プロセス内のスレッドはヒープや静的領域を共有でき、データの受け渡しは速くなりますが、同時書き込みによる不整合を防ぐための同期(ミューテックスや条件変数など)が必要です。
記憶領域の実務的な見取り図
- スタックはスレッドごとに別で、関数のローカル変数などが置かれます。
- ヒープやグローバル領域はプロセス内の全スレッドで共有します。
- ファイルディスクリプタやソケットもプロセス内で共有されることが多く、使い回しやすい反面、同時アクセスの整合性が課題になります。
OSのスケジューリングと実行単位
多くのモダンOSではスレッドがCPUに割り当てられる実行単位です。
複数コアがあれば複数スレッドが本当に同時並行に実行されます。
プロセスは論理的なコンテナとしての単位で、プロセス内のどのスレッドをいつ走らせるかをOSが決めます。
スケジューラはプリエンプティブ(強制切り替え)が一般的で、タイムスライスごとにスレッドを切り替え、待ちが発生しているタスクを他のタスクで有効活用できるようにします。
CPUコアとの関係
- コア数以上のスレッドを作ると、コンテキストスイッチが増えます。適切なスレッド数は、CPU負荷、I/O待ち時間、ランタイムの特性(例:GIL)などで決まります。
- プロセスも複数走らせればマルチコアを活用できますが、プロセス間でのデータ共有はIPC経由になるため、設計の工夫が必要です。
性能と動作の違い
性能面では、切り替えのコスト、データの受け渡しコスト、スループットとレイテンシのバランス、そして障害時の挙動が重要になります。
コンテキストスイッチのコスト
コンテキストスイッチは、CPUが実行する対象(多くはスレッド)を切り替える操作です。
スレッド間の切り替えは比較的軽量ですが、それでもレジスタやスタックの状態保存・復元、キャッシュの乱れが発生します。
プロセスを跨ぐ切り替えではアドレス空間も変わるため、メモリ管理関連(TLBなど)の再設定が入り、一般にスレッド切り替えより負荷が高くなります。
大量に発生するとスループットを下げ、レイテンシのばらつき(ジッタ)を増やします。
プロセス間通信と同期のコスト
プロセス間通信(IPC)は、パイプ、ソケット、メッセージキュー、共有メモリなどがあります。
カーネルを経由したコピーやシステムコールが伴うため、同一プロセス内でのメモリ共有より遅くなる傾向があります。
共有メモリIPCはコピーを避けられ高速ですが、結局は排他制御が必要で、設計難度は上がります。
スレッド間では共有メモリに直接アクセスできますが、ミューテックス、RWロック、アトミック操作といった同期プリミティブの使い方次第で性能が大きく変わります。
IPC手段の特徴比較
手段 | 速度感 | 特徴 |
---|---|---|
パイプ/Unixドメインソケット | 中程度 | 実装容易、プロセス分離を維持、コピーが発生しやすい |
TCPソケット | 中〜低 | ネットワーク越しも可能、ヘッダやバッファ管理のオーバーヘッド |
メッセージキュー | 中程度 | メッセージ指向で管理しやすい、キュー容量管理が必要 |
共有メモリ | 高速 | コピー回避可能、同期が必須で設計が難しい |
スループットとレイテンシの観点
スループットは単位時間あたりの処理量、レイテンシは1件にかかる時間です。
スレッドは軽量なので短命タスクのレイテンシを縮めやすく、プロセスは独立性が高いため同時多発的な障害の影響を減らし、結果として全体のスループットの安定性を高めることがあります。
I/O待ちの多いワークロードではスレッドや非同期I/Oが有利で、CPU集中型の重い処理ではプロセス分割でメモリ局所性を良くしつつ、スレッド数を控えてキャッシュ効率を上げる、といった戦略が有効です。
障害分離とリソース隔離の効果
プロセスは障害やメモリリークを閉じ込めやすく、セキュリティ上の境界としても使えます。
OSの機能(cgroups、ジョブオブジェクト、名前空間など)を併用すれば、CPU時間やメモリ、ファイルアクセスを個別に制限できます。
スレッドは同一プロセス内で運命共同体のため、1つの未処理例外がプロセス全体を止めることもあり、慎重なエラーハンドリングが求められます。
実例でわかる使い分け

Webサーバはマルチプロセスが堅牢
Webサーバでは、各接続の独立性と堅牢性が重要です。
マルチプロセスはワーカーが落ちても他に波及しにくく、グレースフルリロード(サービスを止めずに更新)もしやすい設計が可能です。
Nginxはマスタープロセスと複数のワーカープロセス、Apacheはプリフォーク(接続ごとにプロセス)やワーカ(スレッド併用)など、堅牢性と性能のバランスを取る選択肢があります。
PythonやRubyのアプリケーションサーバも、GILやランタイム特性のためワーカプロセスを複数立ち上げる構成が一般的です。
よくある構成例
- マスタープロセスが設定とライフサイクルを管理し、ワーカーは実処理に専念します。
- ワーカープロセスの中でさらにスレッドを使い、同時接続を効率良く捌く混合モデルも用いられます。
GUIやゲームはマルチスレッドで応答性
GUIアプリやゲームは、画面の描画、入力処理、音声、ネットワークI/O、AIや物理演算など、異なる性質のタスクが同時進行します。
UIスレッドを常に軽く保ち、重い処理をバックグラウンドスレッドへ逃がすことで、フリーズせず滑らかな操作感を実現できます。
多くのフレームワークはUI更新をメインスレッドに制限しているため、スレッド間通信を正しく設計することが重要です。
典型的なスレッド分割
- メイン(UI)スレッド: 入力と描画の制御
- ワーカスレッド: アセット読み込み、ネットワーク、非同期I/O
- 計算用スレッド: 物理演算やAIなどのCPU負荷が高い処理
データ処理は混在設計が有効
大規模データ処理やETL、ストリーム処理では、プロセスとスレッドの混在が効果的です。
各ワーカをプロセスとして分離し、クラッシュやメモリリークを局所化します。
その中でI/O待ちの多い部分をスレッドで並行化すれば、マシン資源を高効率に使えます。
なぜ混在が効くのか
プロセスで障害を閉じ込めつつ、スレッドで細粒度の並行性を確保できるためです。
さらに、プロセス間はメッセージ指向で疎結合に保ち、プロセス内では共有メモリで低レイテンシに処理を進めると、安定性と速度の両立が図れます。
設計指針と注意点
スレッドセーフと排他制御
スレッドセーフとは、複数スレッドから同時に使っても正しく動作する性質を指します。
実現には、ミューテックスやRWロックで共有データを書き換える区間を限定し、ロックの粒度を適切に保つことが重要です。
読み取りが多い場合はRWロック、単純なカウンタにはアトミック操作、可変データの共有を避けるなら不変(イミュータブル)オブジェクトやコピーオンライトといった手法が有効です。
スレッド局所ストレージを活用して、共有そのものを減らすのも効果的です。
ロック運用の基本原則
- 共有データの所有者を明確にし、アクセス経路を減らします。
- ロックの範囲は短く、小さく、必要最小限に保ちます。
- 可能ならばロックをまたぐ処理(I/Oなど)を避けます。
データ競合とデッドロック対策
データ競合は、2つ以上のスレッドが同じデータに対して少なくとも1つが書き込みを行い、その順序が未定義で結果が不定になる現象です。
適切な同期で防げますが、過剰なロックは性能劣化を招きます。
デッドロックは、相互に相手のロックを待ち続ける停止状態で、典型的には複数ロックの取得順序が原因です。
対策としては、ロックの取得順序をプロジェクト全体で統一する、タイムアウト付きロックを用いる、可能ならメッセージパッシングに切り替える、データ構造をロックフリーに置き換えるといった戦術が挙げられます。
ユニットテストや動的解析ツール(スレッドサニタイザなど)も早期検出に役立ちます。
プロセスとスレッドの選び方チェックリスト
最適解は要件によって変わります。
以下の表を参考に、観点ごとに判断してみてください。
観点 | 向いている選択 | 理由 |
---|---|---|
障害隔離とセキュリティ | プロセス | 独立アドレス空間で波及を防ぎ、権限分離もしやすい |
応答性と短命タスク | スレッド | 生成・切り替えが軽く、共有メモリで低レイテンシ |
大量データの共有 | スレッド | コピー不要でデータを直接共有できる(ただし同期が必要) |
言語ランタイム制約(例:GIL) | プロセス | 真の並列実行を得やすい、クラッシュも局所化 |
メモリ使用量の最小化 | スレッド | アドレス空間を共有し、重複を減らせる |
運用とスケールアウト | プロセス | ワーカー追加・再起動・監視が容易で、マシン間分散しやすい |
デバッグ容易性 | プロセス | 問題の切り分けがしやすく、ツールも豊富 |
高信頼の長期稼働 | プロセス + 監視 | 個別再起動やローテーションで劣化を抑えられる |
補足として、1台で最大性能を狙う場合はスレッドで並行性を高め、分散や安全性を重視する場合はプロセス中心に設計するのが出発点として有効です。
そのうえで混在モデルでバランスを取ると、実運用に耐えやすくなります。
まとめ
プロセスは独立性と堅牢性、スレッドは軽量さと即応性が強みです。
OSは主にスレッドを実行単位として扱い、プロセスは境界や管理の単位として機能します。
性能面では、スレッドは共有メモリで低レイテンシを実現しやすい一方、同期の複雑さと不具合の波及に注意が必要です。
プロセスは通信コストが増えがちですが、障害やセキュリティの観点で強力です。
実例としては、Webサーバはマルチプロセスで堅牢に、GUIやゲームはマルチスレッドで応答性を確保し、データ処理は混在設計で安定性と速度を両立するのが定石です。
最後に、要件と運用を見据えた選択と、適切な排他制御・監視・テストの徹底が、現場で長く動くソフトウェアを支えます。