The smallest unit of a CPU’s execution in a program
A thread is the smallest sequence of programmed instructions that can be managed independently by a scheduler, typically a part of the operating system. Each thread is a part of a larger program and contributes to its overall functionality.

A simple example of a thread’s sequence of programmed instructions can be illustrated using Python. In this example, we’ll create a thread that calculates the sum of an array of numbers.
Here’s the code snippet:
from threading import Thread
def calculate_sum(numbers):
total = 0
for num in numbers:
total += num
print(f"The sum of the array is {total}")
# Array of numbers
numbers_array = [1, 2, 3, 4, 5]
# Create a thread to execute the calculate_sum function
thread = Thread(target=calculate_sum, args=(numbers_array,))
# Start the thread
thread.start()
# Wait for the thread to finish
thread.join()In this example, the function calculate_sum contains a sequence of programmed instructions that calculate the sum of an array of numbers. This function is then run in a separate thread using Python's threading library.
Using from threading import Thread allows you to create new threads that can execute functions concurrently with the main thread or with other threads. This is especially useful in scenarios where you have multiple tasks that can be performed independently and simultaneously, improving the overall efficiency and performance of your program.
When you run a standard Python script without explicitly creating new threads, the entire script runs in a single thread, known as the “main thread.”
Most programming languages, including C, C++, Java, Python, and others, are single-threaded by default, meaning they execute one instruction at a time in a sequential manner. However, these languages often provide libraries or frameworks for multi-threaded programming if you need to run multiple tasks concurrently.
That said, there are some programming environments and languages designed with concurrency in mind from the ground up. Here are a few:
- Erlang: Built for massive scalability and maintainability, often used in telecommunications, database, and instant messaging applications.
- Go: Designed with concurrency as a first-class citizen, Go uses goroutines (which are like lightweight threads) to achieve this.
- Rust: While not multi-threaded by default, Rust has first-class support for concurrency and aims to prevent thread-related bugs at compile time.
- Clojure: A modern functional language that runs on the Java Virtual Machine (JVM), Clojure has strong emphasis and built-in support for immutability and asynchronous operations.
- Scala: Also runs on the JVM and has extensive libraries for concurrent and parallel programming.
- Node.js: While JavaScript is single-threaded, Node.js uses non-blocking I/O and asynchronous events to handle many clients concurrently.
- Ada: Often used in real-time systems where concurrent processing is common.
- Akka: Though not a language, it’s a toolkit and runtime for building highly concurrent, distributed, and fault-tolerant systems. It’s often used with Scala and Java.
It’s important to note that even in languages or environments designed for concurrency, the developer still has to make use of these features; they aren’t typically “automatic” in the sense that simply writing code in these languages will make your program concurrent.
Concurrent vs. Parallel Execution
One of the key advantages of using threads is the ability to run multiple threads concurrently, thereby enabling parallel execution of tasks. But here’s the catch: true parallel execution depends on the number of CPU cores available.
The Central Processing Unit (CPU) is essentially the “brain” of a computer, responsible for executing instructions of a computer program. In the context of threads and execution, the CPU plays a critical role in managing how threads run.
In a single-core CPU, threads only appear to run in parallel. What actually happens is a process called time-slicing, where the CPU scheduler allocates CPU time to each thread, creating an illusion of concurrent execution.
For this reasons we can consider a thread (short for “thread of execution”) as the smallest unit of a CPU’s execution in a program. Each thread is a self-contained unit of work that can be executed independently of other threads. Let’s dive into some of the key components that make this possible
Components Unique to Each Thread
Program Counter
The Program Counter is a register within the CPU that specifically keeps track of the location of the next instruction that needs to be executed in a given thread. When the CPU picks up a thread for execution, it sets the Program Counter to point to the first instruction of that thread. As the CPU executes the thread’s instructions, the Program Counter is updated to point to the next instruction in line.
Registers
Registers are small storage locations directly inside the CPU. These are the fastest storage areas available for a thread’s execution. When a thread is scheduled for execution, its own set of registers is loaded into the CPU. These registers might contain data that the thread will use, addresses pointing to other locations in memory, or intermediate results from previous operations.
Stack
The stack is a region of memory assigned to each thread for its exclusive use. While not located in the CPU, the stack is critically important for the CPU’s management of the thread’s execution. The stack holds function call information, local variables, and other data that might be needed during the thread’s execution. The CPU accesses this stack memory when it needs to perform function calls, allocate local variables, or manage the thread’s state.
How Does CPU Manage Threads?
The CPU uses a component called the “scheduler” to decide which thread to run next. When switching from one thread to another, the CPU saves the current state of the executing thread (its Program Counter, Registers, and relevant data in its Stack) so that it can resume the thread later on from the same state. This operation is called a “context switch.”
Multi-core CPUs
Modern CPUs often have multiple cores, which means they can execute multiple threads truly in parallel. Each core has its own set of registers and a Program Counter, allowing each core to independently manage and execute threads.
Thread Safety and Synchronization
The ability for multiple threads to operate without corrupting shared data or resources is called thread safety. Achieving this often involves synchronization mechanisms such as mutexes, semaphores, and barriers. Mutexes, short for “mutual exclusion,” prevent more than one thread from accessing a resource simultaneously, thus eliminating race conditions and data inconsistency.
Thread Priority and Scheduling Algorithms
Not all threads are created equal. Some threads might have higher priority based on the tasks they perform. CPU schedulers often employ algorithms like First-Come-First-Serve (FCFS), Shortest-Job-Next (SJN), or Round Robin to decide which thread should be executed next. Understanding these algorithms is crucial for optimizing thread performance.
Limitations and Drawbacks
While threading offers the promise of faster and more efficient computing, it also brings complexities like potential deadlocks and higher memory usage. Deadlocks occur when two or more threads wait for resources held by each other, creating a standstill. Proper design patterns and synchronization can help mitigate these issues.
Code Optimization
Threaded code can be both a boon and a bane. While it can significantly improve performance, poorly designed multi-threaded code can lead to resource wastage. Optimization techniques like thread pooling and load balancing can help make the most out of multi-threading.
CPU Architecture and Thread Handling
Different CPU architectures, such as ARM and x86, have unique ways of handling threads. Some architectures are more optimized for multi-threading than others. A deeper understanding of your target CPU architecture can offer further optimization opportunities.
Subscribe to my newsletter to get access to all the content I’ll be publishing in the future.






