system-design · beginner

Process vs Thread — Isolation and Shared Memory

Start here

When software “runs,” the operating system does not only store files on disk. It runs units of execution.

Two units you will hear constantly:

You should care because almost every backend, browser, and mobile runtime decision hangs on this trade-off: This lesson is for learners who have never taken an operating systems course. We will go slowly and use pictures in words before jargon piles up.

What you will learn

  1. Define process and thread in plain English.
  2. Explain address space and why isolation matters.
  3. Contrast crash behavior: one thread fault vs one process fault.
  4. Explain why threads need locks (and what a race condition is).
  5. Compare multi-process vs multi-threaded server designs at a beginner level.
  6. Meet concurrency vs parallelism gently.
  7. Preview virtual threads / async models as “not classic OS threads only.”
  8. Practice choosing a model for simple scenarios.

What you should know first

IdeaLevel needed
A program is code that runs and uses memoryBasic
A server handles many usersBasic intuition

No prior OS course required.

Words you need before we begin

TermPlain English
Operating system (OS)Software that manages hardware and running programs (Linux, Windows, macOS).
ProcessA running instance of a program with its own memory space and OS resources.
ThreadAn execution path inside a process; shares the process heap with other threads.
Address spaceThe process’s map of memory addresses it is allowed to use.
HeapArea of memory for objects/data created while the program runs (simplified).
StackPer-thread memory for function call state (simplified).
Context switchOS pausing one execution unit and running another.
Race conditionOutcome depends on unpredictable timing of concurrent access to shared data.
Lock / mutexMechanism so only one thread at a time runs a critical section.
ConcurrencyDealing with many tasks in progress (structure of overlapping work).
ParallelismActually executing multiple tasks at the same wall-clock time (multi-core).

Simple story: offices and workers

Process ≈ an office floor with a locked door and its own filing cabinets.
People inside share those cabinets. People in another office cannot open them without going through official channels (like network calls or files).

Thread ≈ a worker inside that office.
Workers can all grab the same shared whiteboard (shared memory). That is fast — and chaotic if two write different numbers at once.

If one office burns down (process crash), other offices may continue.
If one worker knocks over the shared ink bottle across the whiteboard (memory corruption / bad shared state), every worker in that office is affected.

Where the analogy stops: real OS details include file handles, permissions, and CPU scheduling that offices do not have.

The problem these concepts solve

One user, one loop — not enough

A naïve server might:

while true:
  accept connection
  handle request completely

Only one request at a time. Under two users, the second waits. Throughput is terrible.

To serve many users you need overlapping work. Processes and threads (and later async event loops) are tools for that overlap.

Step-by-step explanation

Step 1 — A process is a running program with walls

When you start an app, the OS creates a process:

Two processes running the same program binary are still **two processes** — two separate memory worlds. Process A generally cannot write into process B’s memory by accident. That isolation is a major reliability and security feature.

Step 2 — A thread is a worker inside the walls

A process starts with at least one thread (the main thread). Programs can create more threads.

All threads in the process typically share:

Each thread usually has its own **stack** for its call chain.

Step 3 — Why threads exist

Creating a brand-new process for every tiny task is heavier:

Threads are cheaper to create (historically) and can communicate by simply reading shared objects — **with great power comes great race conditions.**

Step 4 — Crashes and isolation

EventTypical effect
Thread throws a handled errorOther threads may continue if the program is careful
Bug corrupts shared heapWhole process becomes unsafe
Process crashes / is killedAll threads in it die; other processes can live
Separate process peer diesSurvivors continue; must detect and restart peer

Browsers use multiple processes partly so one bad tab is less likely to kill the entire browser. Many application servers use multiple processes for similar isolation.

Step 5 — Shared memory needs synchronization

Two threads update balance at once:

  1. Both read balance = 100
  2. Both add 20
  3. Both write 120
One deposit is lost. That is a **race condition**.

A lock (mutex) makes a critical section run with mutual exclusion: only one thread at a time. Locks fix races but can create:

Processes avoid accidental shared-memory races by default — they pay with heavier communication.

Step 6 — Concurrency vs parallelism (short)

You can have concurrency without parallelism (single core, time-sliced threads). You can have parallel hardware without a concurrent design (one thread ignores other cores).

Step 7 — Server design sketches

Multi-process server (simplified):

**Multi-threaded server (simplified):** **Async event loop (preview):** Modern platforms mix these (thread pools + processes + async).

Step 8 — Language runtimes add more layers

Examples you will meet later:

You do not need those details memorized now. Remember: **language “thread” may not equal “free unlimited CPU parallelism.”**

Visual mental model

Process isolation

flowchart TB
  subgraph P1 [Process A]
    T1[Thread A1]
    T2[Thread A2]
    M1[Memory A]
    T1 --> M1
    T2 --> M1
  end
  subgraph P2 [Process B]
    T3[Thread B1]
    M2[Memory B]
    T3 --> M2
  end
  P1 -.->|no direct shared heap| P2

Learning question: Can Thread A1 normally write Memory B by accident?

Caption: Separate processes keep separate memory walls.

Threads sharing a heap

flowchart LR
  T1[Thread 1] --> H[Shared heap object]
  T2[Thread 2] --> H
  T1 -->|needs lock| CS[Critical section]
  T2 -->|needs lock| CS

Learning question: What goes wrong if both threads update without coordination?

Caption: Shared memory is fast and race-prone.

Complete worked example: image upload service

Requirements

Option A — thread pool in one process

**Pros:** simple deployment; fast handoff. **Cons:** a native library bug in the scanner can kill all workers; races on shared counters need atomics/locks; hard memory limit for the whole pool.

Option B — multiple worker processes

**Pros:** isolation; scale workers horizontally on other machines easily. **Cons:** more moving parts; cannot share a simple in-memory map without an external store.

Practical hybrid

Many production systems:

Threads still appear **inside** each process for concurrent I/O, but **fault domains** are process/container sized.

How it works in production

What you observe

SignalHint
One container OOM killedProcess memory ceiling hit (all threads share it)
High load average, low progressToo much contention or thrashing
Thread dump shows many BLOCKEDLock contention
Worker process restarts oftenIsolation working; fix root crash

Containers and processes

A Docker container usually runs one main process (plus possible children). Scaling replicas scales processes/containers, not “one giant shared heap across machines.”

Security angle

Separate processes (or sandboxes) help when running untrusted plugins or risky native codecs — a thread is a weaker boundary.

Failure modes

1) Race conditions

2) Deadlocks

3) Overthreading

4) Assuming process death is fine without persistence

5) One multithreaded monolith as SPOF

Trade-offs

ModelStrengthWeakness
Many processesIsolation, simpler mental shared-state storyHigher overhead; IPC needed
Many threadsCheap sharing; good for some shared cachesRaces; whole-process fault domain
Async event loopExcellent connection concurrencyCPU-bound work can stall the loop
HybridBalanceComplexity

Compare with related concepts

TermRelation
ProcessIsolation boundary with own address space
ThreadExecution unit sharing process memory
Coroutine / virtual threadLighter concurrency constructs in runtimes
Goroutine (Go)Runtime-scheduled lightweight threads (model differs from classic 1:1 OS threads)
Actor modelPrefer message passing over shared mutable state

Common misunderstandings

  1. “More threads always means faster.”
Extra threads on a single core just time-slice; too many can slow you down.
  1. “Threads are completely isolated.”
They share the heap; isolation is the process’s job.
  1. “Multi-process means no synchronization needed.”
You still synchronize through the database, queues, and locks across nodes.
  1. “Async code has no concurrency issues.”
Shared mutable state still races across callbacks/tasks.
  1. “The OS thread count equals the user request count in all modern servers.”
Many designs multiplex many requests per thread.

Check your understanding

Race condition on shared memory

Cross-process memory isolation failure

DNS failover

File system formatting error

Stronger isolation if one tab misbehaves

To double network bandwidth automatically

To avoid writing CSS

To use zero memory

Practice

You are designing a PDF rendering feature that uses a native C library known to crash occasionally.

  1. Prefer calling it in-thread in the main API process, or in a separate worker process? Why?
  2. How should the API learn that a worker died mid-job?
  3. Where should the PDF bytes live so any worker can access them?
  4. If two threads share a “rendered page cache” map, what hazard appears?
  5. Name one metric that would show lock contention.

Revision summary

  1. Process = running program with its own memory walls.
  2. Thread = worker inside a process sharing memory.
  3. Isolation vs cheap sharing is the core trade-off.
  4. Shared memory needs synchronization to avoid races.
  5. Crashes often kill the whole process (all its threads).
  6. Real servers mix processes, threads, and async models.
  7. Scale-out clones processes/containers across machines — not one infinite shared heap.

Glossary

TermDefinitionExample
ProcessOS program instance with address spacenode server.js running
ThreadExecution path inside a processWorker thread resizing images
Address spaceProcess memory mapProcess A cannot see B’s heap
Race conditionTiming-dependent incorrect shared updateLost counter increment
Mutex / lockExclusion for a critical sectionLock around balance update
Context switchOS changes running thread/processCPU switches workers
ConcurrencyMany tasks in progress10,000 open connections
ParallelismSimultaneous execution on hardware8 cores run 8 threads
IPCInter-process communicationQueue, socket, pipe
Thread poolReused set of threadsFixed 32 workers

Abbreviations and terminology

ShortFull / note
OSOperating System
CPUCentral Processing Unit
IPCInter-Process Communication
OOMOut Of Memory (process killed for using too much RAM)
GILGlobal Interpreter Lock (CPython detail; advanced)
APIApplication Programming Interface

What to learn next

Primary next lesson: Latency vs Throughput vs Bandwidth

Then: concurrency vs parallelism and language-specific threading lessons when you specialize.

Track: Engineering Foundations

Previous: Latency vs Throughput vs Bandwidth

By Shubham Jain

All articles · Study paths

Shubham Jain · Learning Lab