ホーム第4章: オペレーティングシステム
第4章 2節

プロセスとスレッド

私たちがコンピュータを使うとき、ブラウザを開きながら音楽を聴き、同時にテキストを入力するといったことを当たり前に行っています。このマルチタスクを実現するために、OSは実行中のプログラムを「プロセス」や「スレッド」という単位で細かく管理しています。プログラミングやシステム設計において極めて重要なこの2つの概念の違いを整理します。

1. プログラムとプロセスの違い

日常会話では混同されがちですが、コンピュータサイエンスにおいて「プログラム」と「プロセス」は明確に区別されます。

  • プログラム(Program):静的な存在
    SSDやHDDなどのストレージ上に保存されている「ソースコードをコンパイルした実行ファイル(単なるデータ)」のことです。まだ実行されていません。
  • プロセス(Process):動的な存在
    プログラムがメモリ上にロードされ、CPUが命令の実行を開始した「実行中のプログラムの実体」のことです。

同じブラウザの実行ファイルを複数起動した場合、プログラムは1つですが、実行中の実体であるプロセスは「起動した数だけ」メモリ上に個別に作られます。

2. プロセス(Process)の特徴:メモリの独立壁

OSがプロセスを起動する際、それぞれのプロセスに対して「完全に隔離された独立したメモリ空間」を割り当てます。

あるプロセスは、他のプロセスのメモリ空間をのぞき見することも、書き換えることもできません。このメモリの壁があるため、例えばブラウザアプリがバグでクラッシュしても、同時に動いているエディタアプリに影響が及ぶことはなく、安全性が守られます。

ただし、プロセスを新しく立ち上げるためには、メモリ空間を一から確保して割り当てる必要があるため、起動のコスト(オーバーヘッド)が比較的大きいという特徴があります。

3. スレッド(Thread):プロセスの中の「実行の流れ」

では、1つのアプリの中で「通信しながら、画面の描画を更新し、ユーザーのボタン入力を待ち受ける」といった複数の処理を同時に行いたい場合はどうすればよいでしょうか。

プロセスを複数立ち上げることもできますが、もっと軽量に並行処理を行うための仕組みがスレッド(Thread:糸・実行の細い流れ)です。

スレッドは、「プロセスの中に作られる、実行の流れの最小単位」です。1つのプロセスは、起動時に必ず1つのスレッド(メインスレッド)を持っていますが、必要に応じて内部に複数のスレッド(マルチスレッド)を作り出すことができます。

プロセス (独立したメモリ空間 / ヒープなどを共有) 共有メモリ領域 (コード、グローバル変数、ヒープ領域) スレッド 1 (独自のスタック・PC) スレッド 2 (独自のスタック・PC)
図 4-2:プロセス内部における複数スレッドのメモリ共有モデル

スレッドの最大の特徴は、「同じプロセスに属するスレッド同士は、コードやグローバル変数、ヒープ領域などのメモリ空間を共有する」という点です。

スレッドは自分専用の「スタック領域」と「プログラムカウンタ」だけを持ち、それ以外のメモリはすべて仲間スレッドと共有します。そのため、新しいスレッドの起動や切り替え(コンテキストスイッチ)はプロセスに比べて圧倒的に高速で軽量です。また、メモリを共有しているため、スレッド間でのデータの受け渡しが非常に容易です。

ただし、大きなデメリットとして、メモリ空間を共有しているために、1つのスレッドのバグ(メモリの不正な書き換えなど)が、プロセス内の他のすべてのスレッドを巻き込んでアプリ全体をクラッシュさせてしまうリスクがあります。

4. プロセスとスレッドの比較まとめ

比較項目 プロセス(Process) スレッド(Thread)
定義 実行中のプログラムの単位 プロセス内の実行の流れの単位
メモリ空間 プロセスごとに完全に独立・隔離 同じプロセス内のスレッド間で共有
起動・切り替えコスト 重い(オーバーヘッドが大きい) 軽い(高速に実行可能)
安定性 高い(1つの暴走が他に影響しない) 低い(1つのエラーが全体に波及)
データ共有 プロセス間通信(IPC)が必要で複雑 共有メモリを直接読み書きでき容易

次のセクションでは、複数のスレッドが同じメモリ空間を同時に書き換えようとしたときに発生する深刻な問題(競合状態)と、それを解決するための「排他制御」について学びます。

整理のポイント:プロセスとスレッドの比較

実行中の処理単位である「プロセス」と「スレッド」の決定的な違いを整理しておきましょう。

  • プロセス
    • メモリ空間:完全に独立・隔離。他のプロセスのメモリは原則読み書き不可。
    • リソース・コスト:起動や切り替え(コンテキストスイッチ)の処理負荷が重い
    • 安定性:高い。一つのプロセスがバグで強制終了しても、他のプロセスは影響を受けない。
  • スレッド
    • メモリ空間:同一プロセス内のスレッド間でコードやグローバル変数、ヒープ領域を共有する(スタック領域はスレッドごとに独立)。
    • リソース・コスト:親プロセスのメモリ空間を再利用するため、生成や切り替えが非常に軽い
    • 安定性:低い。共有メモリのバグによって一つのスレッドがクラッシュすると、プロセス全体(他のスレッドも含む)が道連れで強制終了する。