Lesson 4 · Operating Systems

Processes, Threads, and CPU Scheduling

An operating system turns hardware into managed abstractions. Processes provide protected execution environments; threads provide independently scheduled flows of execution inside those environments.

Processes, Threads, and CPU Scheduling concept diagramA visual explanation of the layout and operations shown in this lesson.Process AProcess BThread 1Thread 2Thread 3CPUownsownsscheduler chooses a runnable thread
1

Process as a protected environment

A process includes a virtual address space, executable code, data, open resources, security identity, and at least one thread. Isolation prevents an ordinary memory access in one process from directly modifying another process.

Creating or switching processes involves kernel bookkeeping and address-space concerns. Inter-process communication—pipes, sockets, shared memory, or messages—makes exchange explicit.

  • Isolation improves fault containment
  • Virtual memory gives each process its own address view
  • IPC crosses the isolation boundary deliberately
2

Threads share, stacks do not

Threads in one process normally share code, heap data, and open files, but each thread has its own registers, program counter, and call stack. Sharing makes communication cheap and races possible.

A context switch saves the current execution state and restores another. Excessive switching adds overhead and can disrupt caches even when no useful application work is completed.

  • Shared heap requires coordination
  • Per-thread stacks hold local call state
  • User and kernel threads differ in who schedules them
Key reference

Terms, operations, and practical uses

Execution units

  • ProcessA protected address space with resources and at least one thread.
  • ThreadAn independently scheduled instruction flow inside a process.
  • Context switchSaving one execution state and restoring another.
  • PCBKernel record containing a process's identity, state, scheduling data, and resources.

Scheduling

  • ReadyAble to run but waiting for a CPU.
  • RunningCurrently executing on a CPU core.
  • WaitingBlocked until an event or resource becomes available.
  • PreemptionThe scheduler interrupts running work so another thread can execute.

Concurrency safety

  • Race conditionA result that depends on an uncontrolled ordering of shared operations.
  • Critical sectionCode that must not overlap when it changes a protected invariant.
  • DeadlockA cycle of waiting in which no participant can make progress.
Code example

Protect a shared counter

from threading import Lock, Thread

counter = 0
lock = Lock()

def worker():
    global counter
    for _ in range(3):
        with lock:
            counter += 1

a = Thread(target=worker)
b = Thread(target=worker)
a.start(); b.start(); a.join(); b.join()
print('counter =', counter)
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

int counter = 0;
mutex counterMutex;
void worker() {
    for (int i = 0; i < 3; ++i) {
        lock_guard<mutex> guard(counterMutex);
        ++counter;
    }
}
int main() {
    thread a(worker), b(worker);
    a.join(); b.join();
    cout << counter << '\n';
}
class Main {
    static int counter = 0;
    static synchronized void increment() { counter++; }
    public static void main(String[] args) throws Exception {
        Runnable worker = () -> { for (int i = 0; i < 3; i++) increment(); };
        Thread a = new Thread(worker), b = new Thread(worker);
        a.start(); b.start(); a.join(); b.join();
        System.out.println(counter);
    }
}
Inputtwo workers increment three times each
Outputcounter = 6
Example

Run the example step by step

Output
3

Races and synchronization

A race occurs when correctness depends on an uncontrolled ordering of concurrent operations. Locks protect critical sections; semaphores manage permits; condition variables let threads sleep until a state predicate may have changed.

Synchronization should protect an invariant, not merely a line of code. Keep critical sections small, define lock ownership, and use a consistent lock order.

  • Atomicity: operation appears indivisible
  • Visibility: writes become observable
  • Ordering: events occur in required sequence
4

Scheduling and deadlock

Schedulers balance responsiveness, throughput, fairness, and deadlines. Round-robin time slicing favors interactive fairness, while priority policies risk starvation without aging or other correction.

Deadlock requires mutual exclusion, hold-and-wait, no forced release, and a circular wait. Preventing any one condition is sufficient; a global lock order directly breaks circular wait.

  • Turnaround and response time measure different goals
  • Preemption lets the scheduler interrupt
  • Avoid nested locks or impose one global acquisition order