Concurrency and Thread Safety
Understand visibility, atomicity, thread confinement, and executors before sharing work between threads.
Why it matters
Start from the concept, not the syntax
Meet a concrete situation where this idea earns its place, then state the boundary it guards.
Concurrency lets a program do several things at once—but shared mutable state turns timing into correctness. Threads and executors supply the machinery; synchronization discipline keeps the results deterministic.
By the end of this chapter
Unsynchronized shared state produces timing-dependent wrong totals that pass tests and fail in production.
- Thread and Runnable
- Race conditions
- ExecutorService
Mechanism
How Java expresses the concept
Walk the actual types, rules, and runtime behavior involved—the same behavior described in the Java Language Specification.
The mental model
A `Thread` is a unit of execution. You can extend `Thread` or, better, implement `Runnable` and pass it to a thread; `Runnable` separates the task from the threading mechanism. Calling `start` runs the task concurrently; calling `run` directly just runs it on the current thread.
Shared mutable state is the source of bugs. When two threads read and write the same field without coordination, a race condition produces results that depend on timing. `synchronized` gives a lock so only one thread enters the block at a time; `volatile` makes a single variable visible across threads but is not a mutex.
Prefer an `ExecutorService` over hand-made threads: it pools threads, queues tasks, and lets you shut down cleanly. Submit `Runnable` or `Callable` (which returns a result and can throw). Always `shutdown` the pool so the program can exit.
Concurrency is hard to test because failures are intermittent. Design for it: share as little state as possible, prefer immutable values, and use higher-level tools (`java.util.concurrent`) before reaching for low-level locks.
Concept map
Inspect the building blocks as a whole
Use the map as a structural reference; it shows the pieces and their relationships, not an execution sequence.
Core Java
Threads and concurrency
Concurrency runs several tasks at once. Java gives you threads, the Runnable contract, and executors that manage pools for you.
- 01Thread and Runnable
- 02start vs run
- 03Race conditions
- 04synchronized and volatile
- 05ExecutorService
- 06Shut down pools
Implementation
Encode the smallest runnable example
Write and run the code, then observe the behavior you just predicted with a real Java program.
Runnable snippet path
Predict, run, and change each example
Run a task on a thread
Implement Runnable and hand it to a Thread, then start it.
public class GreetTask implements Runnable {
public void run() {
System.out.println("working");
}
public static void main(String[] args) {
new Thread(new GreetTask()).start();
}
}Remember
Call start, not run, or the task runs on the calling thread.
Change one input, predict the result, then compile or test it before continuing.
Guard shared state
synchronized ensures only one thread at a time changes the counter.
public class Counter {
private int value;
synchronized void increment() { value++; }
synchronized int value() { return value; }
}Remember
Every access to shared mutable state must have a safe visibility and atomicity strategy: immutability, thread confinement, volatile fields, atomics, or locks may be appropriate depending on the invariant.
Change one input, predict the result, then compile or test it before continuing.
Watch out
Break it on purpose, then repair the right layer
Predict the symptom before running the failure case, and close with the completion checklist.
Deliberate failure
Break
Increment a shared counter from two threads without any synchronization
Observe
The final count is occasionally less than the number of increments
Repair
Coordinate every access to shared state with synchronized or a higher-level concurrent tool
Why it matters
Coordinate every access to shared state with synchronized or a higher-level concurrent tool
Completion checklist
- Run work with Thread or Runnable
- Explain and prevent a race condition
- Submit tasks to an ExecutorService and shut it down
Go deeper
Official references
The primary sources behind this chapter. Every claim above stays consistent with them.