Processes vs Threads Explained: How Programs Run Concurrently

Every running program becomes a process. A process owns isolated virtual memory, open files, credentials, and at least one thread. A thread is the unit the CPU schedules. Extra threads inside the same process share the heap and globals but keep a private stack and registers.

Developers meet this distinction in servers, browsers, games, and runtimes. It explains load-only bugs, why one crash can kill an app, why CPython discusses the GIL, and why Node.js, Java, Go, and Chrome choose different concurrency models.

Simple Explanation

A CPU core runs one thread at a time. The OS switches so fast that many apps appear simultaneous. That interleaving is concurrency. Parallelism is two threads running at the same instant on different cores. A process is a locked workshop. Threads are workers sharing that workshop. Another process is a different building.

A web server can handle thousands of connections concurrently even when only a few requests use the CPU at the same instant. A video encoder wants parallelism so multiple cores compress frames together. A UI thread must stay responsive while background threads load data. Choose the model that matches the workload: overlap waiting work, or split CPU work across cores.

Communication follows the same boundary. Threads can pass a pointer to a shared object. Processes must copy bytes through a pipe, socket, or explicit shared-memory mapping. That extra copy is the price of isolation.

How It Works Internally

Starting a program allocates a process control block, a virtual address space, a heap, and a main thread. Linux uses fork or clone plus exec. Windows uses CreateProcess. The MMU isolates process address spaces. The scheduler context-switches threads. Same-process switches are cheaper than process switches because page tables stay put. Blocked threads wait on I/O or locks and do not consume a core.

Kernel threads map 1:1 to language threads in many runtimes. Go goroutines and Java virtual threads multiplex many tasks onto fewer OS threads. Crash boundaries still follow the process.

User -> Browser process -> Network -> Server process -> Database process

Comparison

Process: isolated memory, contained crash, higher create cost, IPC, strong security boundary. Thread: shared memory, cheaper create, direct shared-state access, a bad thread can kill the process. Both can use multiple cores.

Real-World Examples

Browsers isolate tabs in processes and use threads inside renderers. Node.js has one main JavaScript thread plus a libuv pool. CPython threads help I/O; CPU-bound work often uses multiprocessing because of the GIL. Java uses thread pools. Go schedules goroutines. PostgreSQL often uses a process per connection plus shared caches.

Code

from multiprocessing import Process
import os, threading

Process creates a new interpreter and memory space. Thread shares objects; protect increments with a Lock or you can get a race. On Linux, ps aux shows processes and ps -L -p PID shows threads.

Misconceptions and Takeaways

More threads are not always faster. Async overlaps waits on one thread; it is not extra cores. Every process has at least one thread. Do not forcibly kill a single thread if you can avoid it.

  • Processes isolate. Threads share.
  • Use processes for crashes, privileges, and separate machines.
  • Use threads when shared caches must be cheap.
  • Prefer queues over unsynchronized globals.
  • Do not block UI or event-loop threads.

FAQ

What is the difference between a process and a thread?

Difference? Process owns memory. Thread runs inside it.

Can one process have many threads?

Many threads per process? Yes.

Do threads run in parallel?

Parallel? Only with multiple cores.

Why do browsers use multiple processes?

Why multi-process browsers? Isolation and reliability.

What is a race condition?

Race? Unsynchronized shared writes.

What is a deadlock?

Deadlock? Circular lock wait.

How do async and threads compare?

Async vs threads? Async overlaps I/O on one thread. Threads can use extra cores.

Best Practices

Choose processes for isolation, crash containment, and privilege separation; choose threads or lightweight tasks for efficient shared-memory work. Prefer queues or message passing over unsynchronized global state, protect shared data with locks or atomics, keep critical sections short, and avoid blocking UI or event-loop threads.

Related Articles

Next Post Previous Post