⚙️ Process vs Thread

Tiến trình (bộ nhớ riêng) vs Luồng (chia sẻ bộ nhớ)

🔴 Process

Chương trình đang chạy. Bộ nhớ riêng biệt, cách ly hoàn toàn. Crash 1 process ≠ ảnh hưởng process khác.

🔵 Thread

Đơn vị thực thi nhỏ nhất trong process. Chia sẻ bộ nhớ với threads khác cùng process.

1. Process

Process A (PID 1234)          Process B (PID 5678)
┌──────────────────┐           ┌──────────────────┐
│  Code segment    │           │  Code segment    │
│  Data segment    │           │  Data segment    │
│  Heap            │           │  Heap            │
│  Stack           │           │  Stack           │
│  File handles    │           │  File handles    │
└──────────────────┘           └──────────────────┘
   Bộ nhớ RIÊNG                   Bộ nhớ RIÊNG
   ↑ CÁCH LY ↑                    ↑ CÁCH LY ↑

→ 2 processes KHÔNG chia sẻ bộ nhớ
→ Giao tiếp qua IPC (pipe, socket, shared memory)
// Node.js: Multi-process (cluster module)
const cluster = require('cluster');
const os = require('os');

if (cluster.isPrimary) {
    // Master process tạo workers
    const numCPUs = os.cpus().length;
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork(); // Tạo child PROCESS (bộ nhớ riêng)
    }
    cluster.on('exit', (worker) => {
        console.log(`Worker ${worker.process.pid} died`);
        cluster.fork(); // Restart worker
    });
} else {
    // Worker process (mỗi worker = 1 process riêng)
    const express = require('express');
    const app = express();
    app.listen(3000);
}

2. Thread

Process (PID 1234)
┌──────────────────────────────────┐
│  Code segment    (SHARED)        │
│  Data segment    (SHARED)        │
│  Heap            (SHARED)        │
│                                  │
│  ┌─────────┐  ┌─────────┐      │
│  │ Thread 1│  │ Thread 2│      │
│  │ Stack 1 │  │ Stack 2 │      │
│  │ Reg. 1  │  │ Reg. 2  │      │
│  └─────────┘  └─────────┘      │
│                                  │
│  → Threads CHIA SẺ heap, code   │
│  → Mỗi thread có stack RIÊNG   │
└──────────────────────────────────┘
// Node.js: Worker Threads (chia sẻ bộ nhớ)
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

if (isMainThread) {
    // Main thread
    const sharedBuffer = new SharedArrayBuffer(4); // Shared memory!

    const worker = new Worker(__filename, {
        workerData: { sharedBuffer }
    });

    worker.on('message', (msg) => console.log('Result:', msg));
} else {
    // Worker thread (chia sẻ memory với main thread)
    const { sharedBuffer } = workerData;
    const arr = new Int32Array(sharedBuffer);
    arr[0] = 42; // Ghi trực tiếp vào shared memory

    parentPort.postMessage('Done!');
}

3. Bảng So Sánh

Tiêu chí 🔴 Process 🔵 Thread
Bộ nhớ Riêng biệt, cách ly Chia sẻ heap, code
Tạo/hủy Tốn kém (heavy) Nhẹ (lightweight)
Context switch Chậm (đổi toàn bộ) Nhanh (chỉ đổi stack, registers)
Giao tiếp IPC (pipe, socket, SharedMem) Shared memory (trực tiếp)
Crash Không ảnh hưởng process khác Crash thread → crash cả process
Race condition Ít (bộ nhớ riêng) Dễ xảy ra (shared memory)
Ví dụ Chrome tabs, Node cluster Java threads, Go goroutines

4. Race Condition — Vấn Đề Của Threads

⚠️ Race Condition: Khi 2+ threads cùng đọc/ghi shared data → kết quả không đoán trước.

Thread A: read count (0) → +1 → write (1)
Thread B: read count (0) → +1 → write (1)
Kết quả: count = 1 (đáng lẽ phải = 2!) 💀

Giải pháp: Mutex, Semaphore, Atomic operations, Lock-free data structures.

5. Khi Nào Dùng?

Multi-process khi: Cần isolation (security), fault tolerance, khác ngôn ngữ/runtime.

Multi-thread khi: Cần shared memory, performance, lightweight parallelism.

Node.js: cluster (multi-process) cho web server, worker_threads (multi-thread) cho CPU-bound.