Command Palette

Search for a command to run...

Phase 13Advanced14 of 17 in Core Java

Concurrency

Threads, synchronized, volatile and the Java Memory Model, locks, executors, CompletableFuture, concurrent collections, deadlocks and virtual threads.

A computer with eight cores can do eight things at the same moment, and a server spends most of its time waiting for databases and networks. Concurrency is how a Java program uses both facts: it runs several threads at once, so work finishes sooner and waiting doesn't block everything else. It is also the part of Java where the most expensive bugs live, because a program with a concurrency bug can pass every test and still fail once a week in production.

This phase builds the subject from the ground up. Topics 13.1 and 13.2 show what a thread is and how it moves through its life. Topic 13.3 shows the first big danger, the race condition, and the first tool, synchronized. Topic 13.4 explains the rules underneath everything, the Java Memory Model and its happens-before relation, and where volatile fits. Topic 13.5 covers explicit locks, conditions and wait/notify. Topics 13.6 to 13.8 move to the tools you use every day: executors, **CompletableFuture, concurrent collections and atomics. Topic 13.9 is about deadlock and its cousins. Topics 13.10 and 13.11 are modern Java: virtual threads (Java 21), structured concurrency (a preview feature) and scoped values** (final in Java 25).

Every runnable example prints the same output every time. Real thread timing is unpredictable, so the examples wait for threads with join, latches or futures before printing, and print totals and final states rather than the order in which threads happened to run. Where the point of a demo is that the result is unpredictable, the example says so and shows typical output instead. The DSA course's Concurrency-Aware Data Structures module (/dsa/concurrency-ds) puts these tools to work on interview problems such as Print in Order and the bounded blocking queue.

0/11 · 0%
11 topics ~3 h 37 code blocks & diagrams
Start with the first topic
1
13.1

Threads and Runnable

A thread is an independent path of execution inside one program, with its own call stack but sharing the same heap. You describe the work as a Runnable and run it on a new Thread with start(); the JVM maps each such platform thread to an operating system thread.

33 min 5 code practice

2
13.2

Thread Lifecycle, join and sleep

A thread moves through six states: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING and TERMINATED. join waits for another thread to finish, sleep pauses the current one, and interrupt politely asks a thread to stop what it's waiting for.

18 min 3 code practice

3
13.3

Race Conditions and synchronized

When two threads update shared data at the same time without coordination, updates get lost: a race condition. synchronized makes a block or method run by one thread at a time (mutual exclusion) and makes its changes visible to the next thread that takes the same lock.

19 min 3 code practice

4
13.4

volatile and the Java Memory Model

The Java Memory Model (JMM) says when one thread is guaranteed to see another thread's writes. The answer is "when there's a happens-before relationship", created by locks, volatile variables, Thread.start/join and the concurrent utilities. Without one, a thread may see stale or reordered values.

14 min 3 code practice

5
13.5

Locks, Conditions and wait/notify

Threads often need to wait for something (an item in a queue, free space, a signal). The built-in way is wait/notifyAll on a synchronized object; since Java 5, ReentrantLock with Condition does the same with more control: timeouts, interruptible waiting, fairness and several separate wait queues.

15 min 3 code practice

6
13.6

Executors and Thread Pools

Instead of creating a thread per task, you hand tasks to an ExecutorService, which runs them on a reusable thread pool and gives back Futures for their results. Pools bound how many threads run at once, reuse threads, and separate *what* to do from *how* it's scheduled.

19 min 3 code practice

7
13.7

Future and CompletableFuture

CompletableFuture (Java 8) is a Future you can build pipelines on: start work asynchronously, transform results with thenApply, chain dependent calls with thenCompose, combine independent ones with thenCombine/allOf, and handle failures with exceptionally/handle, without blocking a thread at every step.

18 min 4 code practice

8
13.8

Concurrent Collections and Atomics

java.util.concurrent gives you thread-safe building blocks so you rarely need your own locks: atomic variables (AtomicInteger, LongAdder), concurrent collections (ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue) and synchronizers (CountDownLatch, Semaphore, CyclicBarrier).

14 min 4 code practice

9
13.9

Deadlock, Livelock and Starvation

A deadlock is threads waiting for each other forever, usually because they take the same locks in different orders. Livelock is threads busily reacting to each other without progress, and starvation is a thread that never gets a turn. Lock ordering, timeouts and fewer shared locks prevent them.

14 min 3 code practice

10
13.10

Virtual Threads

Virtual threads (Java 21, JEP 444) are threads managed by the JVM instead of the operating system. They're so cheap that you can start one per task, even a million of them, and write simple blocking code that scales like asynchronous code.

14 min 3 code practice

11
13.11

Structured Concurrency and Scoped Values

Structured concurrency (preview in Java 21 to 25) treats a group of related subtasks as one unit: they start in a scope, finish or fail together, and are cancelled together. Scoped values (final in Java 25) share read-only data with everything a task calls, a safer replacement for ThreadLocal.

13 min 3 code practice