The Big Picture: A Thread's Day

A thread is never just "on". At every moment it is in exactly one state: a label that says what it is doing right now. Think of a customer in a shop: in the queue, at the counter, waiting for the item to arrive from the back room, or gone home.

Windows has more fine-grained states internally, but they fit into four easy groups. We learn the simple four first, then add the extra ones Windows uses.

 ┌─────────┐   scheduler picks it    ┌─────────┐
 │  READY  │ ──────────────────────► │ RUNNING │
 └─────────┘                         └─────────┘
   ▲    ▲                              │     │
   │    └── quantum over / preempted ──┘     │ function returns
   │                                         │ or ExitThread
   │ wait is over            must wait       ▼
 ┌─────────┐ ◄───────────────────────┘   ┌────────────┐
 │ WAITING │                             │ TERMINATED │
 └─────────┘                             └────────────┘

4.1 Ready

What it is: A Ready thread is able to run and wants the CPU, but no core is free yet (or a more important thread is using it). It sits in the ready queue.

Windows keeps one ready queue per priority level (0 to 31). When a core becomes free, the scheduler looks at the highest non-empty queue first.

How a thread becomes Ready:

  • It was just created and is set to run.
  • Its wait ended (the file arrived, the lock was released).
  • It was preempted (a higher-priority thread took its core, or its quantum ended).

Why this matters to you: Many threads sitting in the Ready state at once means the CPU is overloaded. You can watch it with the counter \System\Processor Queue Length in Performance Monitor. A common rule of thumb is that a value that stays above about 2 per logical processor suggests the CPU is a bottleneck.

4.2 Running

What it is: A Running thread is executing instructions on a core right now. Only as many threads can be Running as there are logical processors. On an 8-logical-processor PC, at most 8 threads run at the same instant.

A Running thread leaves that state for one of these reasons:

ReasonNext state
Its quantum ends and an equal-priority thread is waitingReady
A higher-priority thread becomes ready (preemption)Ready
It must wait (disk, network, lock, sleep)Waiting
It finishesTerminated

While it runs, a thread can run in two modes (covered in the chapters on the OS):

  • User mode: running the program's own code.
  • Kernel mode: running inside Windows on the program's behalf, for example during a file read.

Task Manager's CPU graph can show "kernel times" (a red line in Resource Monitor) so you can see how much time is spent in each.

4.3 Waiting / Blocked

What it is: A Waiting thread (some books say Blocked) cannot run because it is waiting for something. It uses no CPU while it waits. The scheduler ignores it completely.

What a thread can wait for:

Wait forExample
I/O to finishReading a file, waiting for a network packet
A lock (mutex, critical section)Another thread holds it (Section 7)
An event or semaphore"Data is ready" signal
A timerSleep(1000)
Another thread or process to endWaitForSingleObject(handle, ...)
A page fault to be fixedThe needed memory page must be loaded from disk (Chapter 3)

How it works: the thread asks Windows to wait on a dispatcher object (a kernel object that can be "signalled", such as an event). Windows puts the thread on that object's wait list and picks another thread to run. When the object is signalled, the thread moves back to Ready.

 Thread A: ReadFile(...) ──► state: WAITING (disk working)
                              core 0 now runs thread B instead
 Disk done ──► interrupt ──► A moves to READY ──► later RUNNING again

This is why having many threads is fine when most are waiting: they cost memory but almost no CPU.

Wait reasons. Windows records why a thread waits (for example Executive, UserRequest, WrQueue, DelayExecution, WrPageIn). In PowerShell:

(Get-Process -Name explorer).Threads |
    Select-Object -First 8 Id, ThreadState, WaitReason, PriorityLevel

You will see most threads showing Wait with a reason. Very few show Running.

Stuck threads. A thread that waits forever (because the thing it waits for never happens) is "hung". A program whose UI thread is stuck like this shows "Not Responding". Resource Monitor can help (Section 8.5).

4.4 Terminated

What it is: A Terminated thread has finished. It will never run again. See Section 2.4 for how a thread ends.

What remains:

  • The thread's stack is freed.
  • The kernel's thread object lingers until all handles to it are closed. This lets other code read the exit code and wait on it.
  • Anything waiting for this thread to end is moved to Ready.

When the last thread in a process ends, the process ends too.

4.5 State Transition Diagram

Windows has extra internal states that sit between Ready and Running. You can see them in tools and in the kernel's documentation. Here is the full list:

StatePlain meaning
InitializedThe thread object is being created. Not yet usable.
ReadyCan run; waiting in a ready queue for a free core
StandbyChosen as the next thread for a particular core; waiting for the switch to happen. Only one thread per core can be in Standby
RunningExecuting on a core now
WaitingBlocked on something
TransitionReady to run, but its kernel stack has been paged out to disk. It must be brought back first
TerminatedFinished

Here is the full picture:

        ┌─────────────┐
        │ INITIALIZED │   (created)
        └──────┬──────┘
               │ made runnable
               ▼
        ┌─────────────┐ ◄────────── wait is over (stack in memory)
        │    READY    │ ◄────────── preempted / quantum ended
        └──────┬──────┘ ◄──────┐
               │ scheduler     │ stack paged back in
               │ picks a core  │
               ▼               │
        ┌─────────────┐   ┌────┴───────┐
        │   STANDBY   │   │ TRANSITION │
        └──────┬──────┘   └────────────┘
               │ switch happens        ▲ wait is over, but kernel
               ▼                       │ stack was paged out
        ┌─────────────┐  must wait  ┌──┴──────────┐
        │   RUNNING   │ ──────────► │   WAITING   │
        └──────┬──────┘             └─────────────┘
               │ finished
               ▼
        ┌─────────────┐
        │ TERMINATED  │
        └─────────────┘

Reading it: The loop that matters in daily life is Ready → Standby → Running → (Ready or Waiting) → Ready ... over and over, thousands of times per second. Initialized and Terminated happen once per thread. Transition is rare and only appears when memory is tight.

A typical life:

Initialized → Ready → Standby → Running → Waiting (disk) → Ready
 → Standby → Running → Ready (quantum ended) → Standby → Running → Terminated

Where to see states:

ToolWhat it shows
PowerShell (Get-Process -Id <pid>).ThreadsThreadState (Running, Wait, Ready, Standby, Transition, Terminated...) and WaitReason
Process Explorer (Sysinternals, a free Microsoft tool)Threads tab with state and start address
Performance Monitor \Thread(*)\Thread StateA number for each thread's state (for example 2 means Running, 5 means Waiting)
Performance Monitor \System\Processor Queue LengthHow many threads are ready and waiting

Note: Do not worry if tool labels differ a little from the textbook names. Tools often round states into simpler words.

Summary

StatePlain meaning
InitializedBeing created
ReadyCan run, waiting for a core
StandbyPicked as next on a core, switching in
RunningExecuting on a core now
WaitingBlocked; uses no CPU until the wait ends
TransitionReady, but its kernel stack is on disk
TerminatedFinished
Processor Queue LengthA count of Ready threads; a quick CPU-overload sign