BackendBench
Coffee

Unravel › Java concepts › Concurrency

Concurrency

Threads and shared state

A thread is an independent path of execution.

🔎 Unravel this example

At a glance

Mental model

Several cooks working in one kitchen with one set of ingredients.

What happens, in order
  1. 1new Thread(task).start() begins a new thread that runs taskCalling run() directly does not start a thread; it just runs the code on the current one.
  2. 2join() waits for a thread to finish, and Thread.sleep pauses the current threadBoth throw InterruptedException, which means "someone asked this thread to stop".
  3. 3Threads share heap memoryIf two threads read and change the same variable without coordination, results depend on timing (a race condition).
  4. 4Modern Java (21+) offers virtual threads: cheap threads for blocking code, created with Thread.ofVirtual() or Executors.newVirtualThreadPerTaskExecutor()
Remember
Watch out
Calling run() instead of start()Swallowing InterruptedExceptionUnsynchronised access to shared variablesCreating unlimited threads
Example (highlighted lines explain it)
Thread worker = new Thread(() -> {    try {        Thread.sleep(1000);    } catch (InterruptedException e) {        Thread.currentThread().interrupt();   // keep the stop request alive    }}, "report-worker");worker.start();worker.join();
  1. line 1 uses Thread, the core of Threads and shared state
  2. line 3 uses Thread, the core of Threads and shared state
  3. line 5 keep the stop request alive
  4. line 8 uses start, the core of Threads and shared state
  5. line 9 uses join, the core of Threads and shared state
Read the full explanation (about 1 min)

A thread is an independent path of execution. Several threads run at the same time inside one program and share its memory, which is powerful and the root of most concurrency bugs.

A mental model

Several cooks working in one kitchen with one set of ingredients. They finish faster, but two cooks reaching for the last egg at the same moment is a problem someone has to prevent.

How it works

new Thread(task).start() begins a new thread that runs task. Calling run() directly does not start a thread; it just runs the code on the current one.

join() waits for a thread to finish, and Thread.sleep pauses the current thread. Both throw InterruptedException, which means "someone asked this thread to stop".

Threads share heap memory. If two threads read and change the same variable without coordination, results depend on timing (a race condition).

Modern Java (21+) offers virtual threads: cheap threads for blocking code, created with Thread.ofVirtual() or Executors.newVirtualThreadPerTaskExecutor().

Going deeper

When you catch InterruptedException, either rethrow it or call Thread.currentThread().interrupt() to restore the flag; swallowing it makes the thread impossible to stop cleanly. Creating a raw thread per task does not scale; use an executor. Prefer immutable data and message passing over shared mutable state.

Under the hood

A platform thread maps to an operating system thread with its own stack (about 1 MB by default). The scheduler switches between them, so execution order is not under your control, and the Java Memory Model defines when one thread's writes become visible to another.

Common mistakes

  • Calling run() instead of start().
  • Swallowing InterruptedException.
  • Unsynchronised access to shared variables.
  • Creating unlimited threads.

How Unravel recognises it

When you paste code, Unravel looks for these signs of threads and shared state. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Builds on this

Frequently asked questions

What is Threads and shared state?

A thread is an independent path of execution. Several threads run at the same time inside one program and share its memory, which is powerful and the root of most concurrency bugs.

What are the most common mistakes with Threads and shared state?

Calling run() instead of start(). Swallowing InterruptedException. Unsynchronised access to shared variables. Creating unlimited threads.

How can I see Threads and shared state in real code?

Paste your own Java into Unravel and it will point out where threads and shared state appears, explain how it works at the detail level you choose, and draw the flow of the code around it.