← All posts
7 min read

Processes and Threads: How Running Programs Are Organized

#technology#computer-science#processes#operating-systems
📑 On this page

A program file on storage is not the same thing as a running program. When the operating system launches it, the program gains memory, security identity, open resources, and one or more paths of execution.

Two concepts organize that runtime state:

A process is an isolated container of resources for a running program. A thread is a schedulable execution path inside a process.

Processes provide boundaries. Threads provide concurrent work within those boundaries.

Program versus process

A program is stored code and data, such as an application executable.

A process is a live instance. It includes:

  • A virtual address space
  • Loaded code and libraries
  • Memory allocations
  • Open files and sockets
  • Security credentials
  • Environment variables
  • At least one thread

Launching the same application twice can create two processes with separate state.

The program file is like a recipe. Each process is one active kitchen following that recipe with its own ingredients and tools.

Process isolation

Each process normally receives its own virtual address space.

The address 0x1000 in process A can refer to different physical memory from 0x1000 in process B. The operating system and processor memory-management hardware enforce the mapping.

Isolation prevents ordinary accidental access:

  • A text editor cannot directly overwrite a browser's private memory.
  • A crashed game does not automatically destroy an email client's state.
  • Processes can run under different user permissions.

Isolation is not absolute. The OS provides deliberate communication methods, and security vulnerabilities can sometimes break boundaries.

What a thread contains

Threads in one process share:

  • Process memory
  • Loaded code
  • Open files
  • Many operating-system resources

Each thread has its own:

  • Instruction position
  • CPU register state
  • Stack
  • Scheduling state

The stack holds function-call information and local values for that execution path.

Sharing memory makes thread communication fast, but it creates coordination problems. Two threads can read and update the same data at unsafe times.

Concurrency and parallelism

Concurrency means multiple tasks make progress during overlapping time.

Parallelism means tasks execute literally at the same instant on different processing resources.

On one CPU core, the scheduler can switch among threads, creating concurrency. On several cores, multiple threads can run in parallel.

A program can be concurrent without being parallel, and parallel execution is one method for implementing concurrent work.

This distinction matters because concurrency still introduces ordering and synchronization issues even when only one thread runs at a time.

A concrete example: a web browser

Modern browsers often use multiple processes:

  • Browser interface process
  • Renderer processes for sites or tabs
  • GPU process
  • Network or utility processes

Inside a renderer process, threads may handle:

  • Main page logic
  • Compositing
  • Worker scripts
  • Input
  • Supporting runtime work

Multiple processes improve isolation. If one renderer crashes, the entire browser may survive. Site isolation can also make it harder for one page to inspect another.

The cost is extra memory and inter-process communication.

Thread synchronization

Suppose two threads increment the same counter:

read current value
add one
write new value

If both read 10 before either writes, both may write 11. One increment is lost.

This is a race condition: the result depends on timing.

Programs use synchronization tools:

  • Mutexes
  • Semaphores
  • Atomic operations
  • Condition variables
  • Message queues

These tools coordinate access, but misuse can create deadlocks, contention, or poor performance.

Shared mutable state is powerful and dangerous.

Inter-process communication

Processes need explicit methods to exchange information:

  • Pipes
  • Sockets
  • Shared memory
  • Files
  • Message queues
  • Operating-system signals

These mechanisms differ in speed, structure, security, and complexity.

Shared memory can be fast but requires synchronization. Message passing can provide clearer ownership but adds serialization and copying overhead.

Operating systems check permissions and manage endpoints, preserving process boundaries while enabling cooperation.

Creating a process

When launching an application, the OS:

  1. Creates process-management structures.
  2. Establishes a virtual address space.
  3. Maps program code and libraries.
  4. Sets identity and environment.
  5. Creates an initial thread.
  6. Places the thread in the scheduler's runnable set.

Some systems create processes by cloning aspects of a parent and then loading a different program. Others use dedicated creation APIs.

The process may create additional threads as its workload grows.

Context switching

To switch threads, the operating system preserves the current thread's processor state and loads another's.

A context switch can disturb caches and translation structures. Excessive switching consumes time without advancing application work.

Schedulers therefore try to balance responsiveness with efficiency. Tiny time slices improve responsiveness but increase switching overhead; long slices reduce overhead but can make interactive tasks wait.

Switching between threads in one process can be cheaper than switching between isolated processes, but the exact cost depends on hardware and OS behavior.

Thread pools and asynchronous work

Creating an unlimited thread for every task is inefficient. Threads consume memory for stacks and add scheduling overhead.

Applications often use a thread pool: a controlled set of reusable worker threads receives tasks from a queue.

Asynchronous programming can wait for network or storage operations without dedicating a blocked thread to every request. Completion events resume the appropriate logic later.

Asynchronous does not mean automatically parallel. It is a way to structure waiting and concurrency efficiently.

Failure boundaries

An unhandled error in one thread can terminate its entire process because all threads share process state.

A process crash usually does not directly terminate independent processes, though a supervising application may choose to restart or close related components.

This trade-off influences architecture:

  • Threads share data efficiently but share failures.
  • Processes isolate memory and crashes but communicate less directly.

Systems choose boundaries based on trust, performance, and reliability.

Common misunderstandings

"A process is the application window"

One application can use many processes, and one process can own multiple or no visible windows.

"Threads have separate memory"

Threads in one process share its address space, though each thread has its own stack and register state.

"Concurrency requires multiple CPU cores"

A scheduler can interleave several tasks on one core. Multiple cores add true parallel execution.

"More threads always make a program faster"

Dependencies, synchronization, memory bandwidth, scheduling overhead, and limited cores can erase the benefit.

Knowledge check

1. What is the main difference between a program and a process?

A program is stored code; a process is a running instance with memory, resources, identity, and threads.

2. What do threads in one process share?

They share process memory, loaded code, and many resources, while retaining separate stacks, registers, and execution positions.

3. What is a race condition?

It is a bug in which the result depends on uncontrolled timing among concurrent operations.

4. Why might software choose several processes instead of only threads?

Processes provide stronger memory, security, and crash isolation.

The one idea to remember

Processes isolate running programs; threads divide execution within a process.

The choice between them balances communication speed, shared state, parallelism, security, resource cost, and failure containment.

Next, we will examine how the scheduler gives all these runnable threads turns on a limited number of CPU cores.