Java Thread Synchronization: Critical Sections, Locks & Race Conditions

When multiple threads concurrently read and write to the same shared mutable variables on the Heap, Race Conditions corrupt the data. Synchronization uses Monitor Locks (Intrinsic Locks) to guarantee that only one thread can execute a critical section at any given moment.

The Problem: Race Condition Demo

class Counter {
    int count = 0;

    // Synchronized keyword guarantees mutually exclusive access:
    public synchronized void increment() {
        count++; // 3 steps: read, add 1, write back!
    }
}

public class SynchronizationDemo {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10_000; i++) counter.increment();
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10_000; i++) counter.increment();
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        // Guaranteed to be exactly 20,000 thanks to synchronization!
        System.out.println("Final Counter: " + counter.count);
    }
}

Synchronized Block (Fine-Grained Locking)

Prefer synchronized blocks over synchronized methods to reduce thread lock contention:

public void processPayment(double amount) {
    // Non-critical code runs concurrently without locks:
    logPaymentAttempt(amount);

    // Critical section: Locks only during balance modification
    synchronized (this) {
        this.balance -= amount;
    }
}

Next Step

Improper locking can cause Deadlocks. Let us explore Deadlock prevention, wait(), and notify(). Proceed to: Java Deadlock & Wait / Notify →

Frequently Asked Questions (FAQ)

Q1. What is a Race Condition in Java multithreading?
A race condition occurs when two or more threads concurrently access and mutate shared data without synchronization, causing unpredictable bugs and corrupted final state depending on which thread executes first.
Q2. What is the difference between a Synchronized Method and a Synchronized Block?
A synchronized method locks the entire method on the current object instance (this). A synchronized block locks only a specific critical section of code, allowing unrelated code to run concurrently, delivering superior performance.
Q3. What is the purpose of the 'volatile' keyword in Java?
The 'volatile' keyword ensures visibility across CPU cores: it guarantees that reads and writes to a variable bypass CPU caches and directly interact with main RAM, ensuring all threads immediately see updates.

Explore Related Java Tutorials

Accelerate your Java mastery by studying these tightly connected core tutorials:

Deadlock Prevention →

Avoiding locking traps.

Multithreading Basics →

Threads and concurrent execution.

Executor Framework →

Thread-safe concurrency.

Virtual Threads →

Concurrency in modern Java 21.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!