プロセスとスレッドの違いとは - メモリ空間 / 生成コスト / 通信方法を比較
プロセスとスレッドの違いをメモリ空間 / 生成コスト / 通信方法の 3 軸で比較。Node.js での使い分け、Lambda の実行環境、データ競合とコンテナの PID 1 の落とし穴まで解説
プロセスとスレッドとは
プロセスは OS が管理するプログラムの実行単位で、独立したメモリ空間を持つ。スレッドはプロセス内の実行単位で、同じメモリ空間を共有する。
比較
違いはすべて「メモリ空間を隔離するか」から派生する。隔離のぶんプロセスは生成も通信も高くつき、その代償として片方が落ちても他方は動き続ける。
| 観点 | プロセス | スレッド |
|---|---|---|
| メモリ | 独立 (隔離) | 共有 |
| 生成コスト | 高い | 低い |
| 通信 | IPC (パイプ、ソケット) | 共有メモリ (直接) |
| 障害の影響 | 他プロセスは動き続ける | 同一プロセス内の全スレッドに影響 |
| 例 | Chrome のレンダラープロセス | Java のスレッド |
プロセス A (メモリ空間 A) プロセス B (メモリ空間 B)
├── スレッド 1 ├── スレッド 1
├── スレッド 2 └── スレッド 2
└── スレッド 3
↑ 同じメモリを共有 ↑ A とは独立したメモリ
Node.js のモデル
Node.js が単一スレッドなのは JavaScript を実行する部分だけである。1 つのプロセスの中でメインスレッドがイベントループを回し、ファイルシステム操作や dns.lookup などは libuv のスレッドプール (既定 4 スレッド) が裏で処理して結果をイベントループへ返す。「Node.js はスレッドを 1 本しか使わない」わけではない点が、性能を読むときの前提になる。
メインスレッド: [イベントループ] → I/O を非同期で処理
Worker Threads: CPU バウンドな処理を別スレッドで実行
child_process: 別プロセスでコマンドを実行
cluster: 複数プロセスでリクエストを分散
| 方法 | 用途 |
|---|---|
| イベントループ | I/O バウンド (API 呼び出し、DB) |
| Worker Threads | CPU バウンド (画像処理、暗号化) |
| cluster | マルチコア活用 (HTTP サーバー) |
Lambda のプロセスモデル
Lambda の実行環境は、処理中に別のリクエストを受け付けない。同時に届いた数だけ実行環境が並ぶので、環境の内側ではスレッド間競合を気にせず書ける。一方で環境は呼び出しの合間に凍結され、次の呼び出しで解凍して再利用される。ハンドラーの外で初期化した DB 接続などはそのまま引き継がれるため、プロセスが毎回作り直される前提でグローバル変数に状態を持つと、後続の呼び出しへ漏れる。
リクエスト 1 → 実行環境 A (プロセス A)
リクエスト 2 → 実行環境 B (プロセス B)
リクエスト 3 → 実行環境 C (プロセス C)
データ競合
スレッドは同じメモリ空間に居るため、同じ変数を同時に読み書きするとデータ競合が起きる。ただし Node.js の Worker Threads は既定で値をコピーして渡すので、競合が問題になるのは SharedArrayBuffer を明示的に共有した場合に限られる。競合の正体は「読み取り → 加算 → 書き込み」の 3 段が別スレッドの操作に割り込まれることで、下の例では 2 回の加算が 1 回分しか残らない。
// ❌ データ競合 (Node.js の SharedArrayBuffer)
// スレッド A: counter++ (read → increment → write)
// スレッド B: counter++ (read → increment → write)
// 結果: 2 ではなく 1 になる場合がある
// ✅ Atomics で安全にアクセス
Atomics.add(sharedArray, 0, 1);
コンテナとプロセス
Docker コンテナは通常 1 プロセスを実行する (PID 1)。複数プロセスが必要な場合はサイドカーパターンで別コンテナに分離する。落とし穴は PID 1 の特性で、Linux では PID 1 はハンドラーを登録していないシグナルの既定動作が働かない。アプリが SIGTERM を自分で処理しないと docker stop で終わらず、猶予時間の経過後に SIGKILL で落とされるため、後片付けが走らない。
使い分けの基準は単純で、障害やメモリを隔離したいならプロセス、状態を高速に共有したいならスレッドである。迷ったらまずプロセス分離を選び、通信コストが実測で問題になってからスレッドへ寄せる方が事故は少ない。
この記事は役に立ちましたか?
関連用語
並行処理 (Concurrency) とは - 並列処理 (Parallelism) との違い
Concurrency (並行処理) の意味を解説。複数のタスクを論理的に同時進行させる手法で、物理的に同時実行する並列処理 (Parallelism) とは区別される。Node.js / Go / Rust の並行処理モデルの違いも紹介。
Worker Threads
Node.js で CPU 集約的な処理をメインスレッドをブロックせずに別スレッドで実行する仕組み
goroutine
Go の軽量スレッドで、数十万規模の並行処理を低コストで実現する
スレッドプール
事前に生成したスレッドを再利用し、スレッド生成のオーバーヘッドを削減する並行処理パターン
Node.js
Chrome V8 エンジン上で動作するサーバーサイド JavaScript ランタイム
Web Worker
ブラウザのメインスレッドとは別のスレッドで JavaScript を実行し、UI のブロッキングを防ぐ仕組み
関連する記事
技術書の読書メモ術 - 読んだ内容を確実に定着させる記録法
技術書の内容を定着させる 3 行メモ法と、ツール選び、メモを実務に活かす仕組みを紹介します。
読書メモは未来の自分への手紙である
技術書を読んだときのメモは、数ヶ月後 / 数年後の自分が読み返して助かる贈り物になります。「あのとき何を考えていたか」を残す読書メモの書き方と、長期的な活用法を紹介します。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。