Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 1

Threads vs. Processes: Resource Sharing & Scheduling

Recommended resources

Welcome to your first lesson in the course on Operating Systems, Parallel Processing, and Distributed Systems. Given your background in computer science and operating systems, this module will serve as a bridge, solidifying core concurrency concepts before we move into the more complex territory of parallel and distributed computing.

You've mentioned that while you have a basic understanding of threads, you'd appreciate a deeper clarification. This lesson is designed to provide exactly that. We will start by distinguishing between processes and threads, focusing specifically on two fundamental aspects: how they share system resources and how the operating system schedules them for execution. Mastering this distinction is the first crucial step toward understanding modern concurrent programming.

From Programs to Processes: A Quick Recap

As you know from your OS studies, a program is a static set of instructions stored on a disk. When you execute it, the operating system loads it into memory and it becomes a process—a program in execution. The OS allocates resources to this process, creating an isolated environment for it to run. This includes its own private virtual address space, file handles, and other system resources. This isolation is a key feature, providing robustness by preventing one misbehaving process from affecting others.

To quickly refresh these foundational ideas, please watch the first part of this short video from ByteByteGo.

FANG Interview Question | Process vs Thread

This video provides a concise, animated explanation of a program, a process, and the resources associated with a process.

Watch the segment from the beginning until the definition of a process. Pay close attention to the concept of an independent memory address space and process isolation.


Introducing Threads: Execution Within a Process

A process, with its heavy armor of resources and a protected address space, can be thought of as a container. Initially, this container holds a single flow of execution, often called the main thread. However, we can create additional, concurrent execution flows within the same process container. These are known as threads.

A thread, sometimes called a lightweight process, is the basic unit of CPU utilization. It comprises a thread ID, a program counter, a register set, and a stack. Crucially, it shares with other threads belonging to the same process its code section, data section, and other operating system resources, such as open files.

The following diagram illustrates this relationship. On the left is a traditional single-threaded process. On the right is a multi-threaded process, where multiple threads share the same process-wide resources but each maintains its own execution context.

This diagram compares a single-threaded process with a multi-threaded one. Notice that resources like code and heap are shared among all threads in the multi-threaded process, while each thread has its own private registers, program counter, and stack.

Resource Sharing: The Core Distinction

The primary difference between processes and threads lies in their memory model.

  • Processes are heavyweight and independent. Each process has its own separate virtual address space. This strict isolation means that if you want two processes to communicate, you must use Inter-Process Communication (IPC) mechanisms like pipes, sockets, or shared memory segments, which are managed and brokered by the kernel. This makes inter-process communication relatively slow and complex.

  • Threads are lightweight and interdependent. All threads within a single process share the same address space. This means they can directly access the same global variables and heap memory. This makes communication between threads trivial and extremely fast—one thread can write a value to memory, and another can immediately read it. However, this power comes with a risk: since there is no protection between threads, one faulty thread can corrupt the memory of all other threads in the process, potentially crashing the entire application.

To see a practical demonstration of this fundamental difference, the next video uses simple C programs to highlight how variables are handled in multi-process versus multi-threaded environments.

Difference between processes and threads

The presenter from the CodeVault channel provides a hands-on comparison of processes and threads using code.

Watch the following two segments carefully: First, observe how process IDs differ when creating new processes versus new threads. This demonstrates that the OS sees processes as distinct entities, while threads are components of a single process. Next, focus on the core experiment with a shared variable, from the address space explanation to the conclusion of the variable test. Notice how an increment to a variable in one process is not visible to the other, whereas an increment in one thread is immediately visible to its sibling thread.

To solidify this concept with a more formal definition, let's turn to a chapter from Computer Systems Fundamentals.

6.2. Processes vs. Threads

This text provides clear definitions and a direct comparison of what resources are shared versus what are unique to a thread.

Please read the following parts: Start with the introduction, from the definitions of process and thread. Continue to the "Multithreading" section, reading the explanation of how threads share memory but have separate stacks, and how this separates the concepts of scheduling and resource ownership. Finally, jump to the section "Thread Models" and study the table, which provides a concise summary of what is unique per thread versus what is shared within the process under the POSIX model.


Scheduling: Heavyweight vs. Lightweight Context Switching

The second major point of distinction is how the operating system schedules processes versus threads. The OS scheduler's job is to switch the CPU between different tasks to give the illusion of parallelism. This act of switching is called a context switch.

  • Process Context Switch: When the OS switches from one process (P1) to another (P2), it must save the complete context of P1 (CPU registers, program counter, stack pointer) and, critically, it must switch the virtual memory context. This involves changing the page table registers in the Memory Management Unit (MMU) to point to P2's address space. This memory map switch is a computationally expensive operation, flushing parts of the processor's caches and translation lookaside buffer (TLB). This is why process context switches are considered "heavyweight."

  • Thread Context Switch: When the OS switches between two threads (T1 and T2) that belong to the same process, it still needs to save and restore the thread-specific context (registers, program counter, stack pointer). However, because both threads share the same address space, the OS does not need to change the virtual memory context. The page table remains the same. This avoidance of a memory map switch makes thread context switching significantly faster. This is why thread context switches are "lightweight."

The ByteByteGo video you watched earlier also covers this point well. You can re-watch the final segment for a clear visual on this.

FANG Interview Question | Process vs Thread

This part of the video explains and visualizes the process of a context switch.

Watch the segment on context switching. Focus on the key reason why switching between threads is faster than switching between processes.


Summary of Differences

Let's consolidate the key distinctions in a simple table. This summarizes the trade-offs you make when choosing one model over the other.

Feature Process Thread
Weight Heavyweight Lightweight
Address Space Each process has its own separate address space. Threads within a process share the same address space.
Resource Sharing Resources (memory, files) are not shared by default. Resources are shared by default among threads of the same process.
Communication Requires explicit Inter-Process Communication (IPC), which is slower. Fast and simple communication through shared memory (global variables, heap).
Creation & Switching Slow to create; context switching is expensive. Fast to create; context switching is cheap.
Fault Isolation High. A crash in one process does not affect other processes. Low. A crash in one thread can bring down the entire process.
Scheduling Unit The process is the unit of resource ownership. The thread is the unit of execution/scheduling.

Conclusion

In this lesson, we have drawn a clear line between processes and threads based on resource sharing and scheduling. The main takeaway is that a process acts as a robust, isolated container for resources, while a thread is a nimble, lightweight path of execution within that container. This design creates a fundamental trade-off: processes offer safety and isolation at the cost of high overhead for creation and communication, whereas threads offer efficiency and easy communication at the cost of safety.

Understanding this trade-off is essential for designing concurrent applications. As we move forward, you will see how almost all modern parallel programming models are built upon the concept of threads.

In our next lesson, we will look closer at the lifecycle of a thread and explore the two main ways they are implemented: user-level threads and kernel-level threads. This distinction has significant consequences for scheduling, performance, and how your multithreaded applications interact with the operating system.