OS Concepts Explained — Processes, Threads & Scheduling Algorithms
Operating system concepts like processes, threads, and CPU scheduling determine how efficiently your computer runs multiple programs at once.
What You’ll Learn
In this tutorial, you’ll learn the difference between processes and threads, how CPU scheduling algorithms work, and what happens during a context switch — with Python simulations.
Why It Matters
Every running app on your computer is managed by the OS scheduler. Choosing the right scheduling algorithm can mean the difference between a responsive system and a frozen one. Understanding these concepts is critical for system programming, performance tuning, and interview preparation.
Real-World Use
When you have 20 browser tabs open while running a video call and a code editor, the OS is constantly switching between these processes — giving each one a slice of CPU time. Durga Antivirus Pro uses OS-level process monitoring to detect suspicious behavior across all running processes.
stateDiagram-v2 [*] --> New New --> Ready: Admitted Ready --> Running: Scheduler dispatch Running --> Ready: Interrupt Running --> Waiting: I/O or event wait Waiting --> Ready: I/O or event complete Running --> Terminated: Exit Terminated --> [*]
Processes vs Threads
A process is a program in execution — it has its own memory space, file handles, and system resources. A thread is the smallest unit of execution within a process. Threads share the same memory space and resources of their parent process.
Think of a process like a kitchen in a restaurant. Each kitchen has its own stoves, refrigerators, and utensils (resources). Threads are the chefs working in that kitchen — they share the same equipment and ingredients but work on different tasks.
| Feature | Process | Thread |
|---|---|---|
| Memory | Isolated address space | Shares parent’s address space |
| Creation | Slow (OS allocates resources) | Fast (lightweight) |
| Communication | IPC (pipes, sockets, shared memory) | Direct memory access |
| Context switch | Heavy (TLB flush, page table switch) | Light (registers only) |
| Fault isolation | One crash doesn’t affect others | One thread crash kills all threads |
Context Switching
When the OS switches from running one process to another, it performs a context switch. The current process’s state (registers, program counter, stack pointer) is saved to its Process Control Block (PCB), and the next process’s state is loaded.
import time
class PCB:
"""Process Control Block simulation"""
def __init__(self, pid, name):
self.pid = pid
self.name = name
self.state = "New"
self.program_counter = 0
self.registers = {}
self.saved_context = {}
def save_context(self):
self.saved_context = {
"pc": self.program_counter,
"registers": self.registers.copy()
}
print(f"[{self.pid}] Context saved: PC={self.program_counter}")
def restore_context(self):
self.program_counter = self.saved_context.get("pc", 0)
self.registers = self.saved_context.get("registers", {}).copy()
print(f"[{self.pid}] Context restored: PC={self.program_counter}")
def run(self, instructions=3):
self.state = "Running"
for i in range(instructions):
self.program_counter += 1
print(f"[{self.pid}] Executing instruction {self.program_counter}")
time.sleep(0.1)
self.state = "Ready"
p1 = PCB(1, "Browser")
p2 = PCB(2, "Music Player")
print("--- Context Switch Simulation ---")
p1.save_context()
p2.restore_context()
p2.run(2)
p2.save_context()
p1.restore_context()
p1.run(2)Expected output:
--- Context Switch Simulation ---
[1] Context saved: PC=0
[2] Context restored: PC=0
[2] Executing instruction 1
[2] Executing instruction 2
[2] Context saved: PC=2
[1] Context restored: PC=0
[1] Executing instruction 1
[1] Executing instruction 2CPU Scheduling Algorithms
First-Come, First-Served (FCFS)
The simplest algorithm — processes run in the order they arrive. Like a single checkout line at a supermarket.
def fcfs(processes):
"""FCFS Scheduling"""
time = 0
for name, burst in processes:
print(f"Time {time}-{time+burst}: {name}")
time += burst
print(f"Total time: {time}")
print(f"Avg waiting: {sum(sum(p[1] for p in processes[:i]) for i in range(len(processes))) / len(processes):.1f}")
fcfs([("P1", 6), ("P2", 8), ("P3", 7), ("P4", 3)])Expected output:
Time 0-6: P1
Time 6-14: P2
Time 14-21: P3
Time 21-24: P4
Total time: 24
Avg waiting: 10.2Round Robin
Each process gets a fixed time quantum (e.g., 4 ms). If a process doesn’t finish within its quantum, it’s preempted and goes to the back of the ready queue.
from collections import deque
def round_robin(processes, quantum=4):
queue = deque([[n, b] for n, b in processes])
time = 0
while queue:
name, burst = queue.popleft()
run = min(burst, quantum)
time += run
remaining = burst - run
print(f"Time {time-run}-{time}: {name} (remaining {remaining})")
if remaining > 0:
queue.append([name, remaining])
round_robin([("P1", 10), ("P2", 5), ("P3", 8)], 4)Expected output:
Time 0-4: P1 (remaining 6)
Time 4-8: P2 (remaining 1)
Time 8-12: P3 (remaining 4)
Time 12-16: P1 (remaining 2)
Time 16-17: P2 (remaining 0)
Time 17-21: P3 (remaining 0)
Time 21-23: P1 (remaining 0)Common Mistakes
- Confusing process with thread: A process has its own memory space; threads share memory. Killing a thread doesn’t clean up resources the way killing a process does.
- Assuming Round Robin is always fair: The time quantum matters. Too small → excessive context switching overhead. Too large → FCFS behavior.
- Ignoring context switch cost: Each context switch takes 1-100 microseconds. With 1000 switches/second, that’s 10% CPU overhead.
- Thinking more processes = more parallelism: On a single-core CPU, only one process runs at a time. The rest are waiting.
- Forgetting about the I/O wait: A process waiting for disk or network is in “Waiting” state, not consuming CPU cycles.
Practice Questions
What is a context switch? Saving the state of the currently running process and loading the saved state of another process so it can resume execution.
Why are threads called “lightweight”? They share memory and resources with their parent process, so creating and switching between threads is faster than processes.
What’s the starvation problem in priority scheduling? Low-priority processes may never get CPU time if higher-priority processes keep arriving.
How does Round Robin prevent starvation? Every process gets a fair time slice in a cyclic order, ensuring all processes make progress.
What happens during a context switch to the CPU cache? The cache is flushed or invalidated, causing cache misses when the new process runs — this is a major cost of context switching.
Challenge
Implement the Multi-Level Feedback Queue algorithm. Create three queues with priorities 0, 1, 2. A new process enters queue 2. If it doesn’t finish within its quantum, it moves down one queue. Queues 0 (highest) runs first using Round Robin.
Real-World Task
Open Task Manager (Windows) or htop (Linux). Watch how processes change states. What’s the CPU usage of idle processes? Which scheduling algorithm does your OS use?
Mini Project: Scheduler Simulator
Build a Python script that simulates all four scheduling algorithms (FCFS, SJF, Round Robin, Priority). Generate random processes. Compare average waiting time, turnaround time, and throughput for each algorithm.
Security angle: OS schedulers isolate processes so malware can’t starve legitimate programs. This same isolation is used by Durga Antivirus Pro to scan without freezing your system.
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
What’s Next
Congratulations on completing this OS Concepts tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro