Synchronization in Java

Synchronization in Java

May 11th, 2026
2777
8:00 Minutes

Synchronization in Java is what you need to know to deal with complicated and multithreaded applications. Java synchronization is a mechanism that makes sure only one thread can access a shared resource at a time. Your applications will no longer need to struggle with race conditions and data inconsistency.

So, would you like to know more about this impactful tool? I have created this blog, What is Synchronization in Java, to serve as a guide for you to explore what Java Synchronization truly means. You will get to know its importance after going through the fundamental concepts of synchronized keywords and volatile variables. Let's master thread synchronization in your applications with practical examples, too.

Master Java Programming with Java Training

Boost your coding skills and gain hands-on knowledge in Java.

Explore Now

What is Synchronization in Java?

Let's cover up the first question popping in your head - what is Synchronization in Java? It is a mechanism that makes sure that multiple threads can safely access shared resources. This is done without resulting in any kind of inconsistency or data corruption. It makes sure that only one thread can access a particular section of code or object at a time. It prevents issues like race conditions and memory consistency errors. Let's take a look at the Java program below that shows synchronization:

class Counter {
    private int c = 0; // Shared variable

    // Synchronized method to increment counter
    public synchronized void inc() {
        c++;
    }

    // Synchronized method to get counter value
    public synchronized int get() {
        return c;
    }
}

public class igm {
    public static void main(String[] args) {
        Counter cnt = new Counter(); // Shared resource

        // Thread 1 to increment counter
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                cnt.inc();
            }
        });

        // Thread 2 to increment counter
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                cnt.inc();
            }
        });

        // Start both threads
        t1.start();
        t2.start();

        // Wait for threads to finish
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Print final counter value
        System.out.println("Counter: " + cnt.get());
    }
}

Output

This is what the expected output would look like -

Counter: 2000

Explanation

Here is an explanation -

  • Threads T1 and T2 together access the same shared counter variable.
  • Both inc () and get () are synchronized methods. This means only one thread can run either one at a time.
  • Synchronized means only one thread can run those methods at once.
  • This stops threads from colliding when they update shared data.
  • Synchronization makes sure both threads update the counter correctly.
  • The final result shows the correct total of all increments.

Read Also: Java Tutorial For Beginners

What are synchronized blocks in Java?

Synchronized blocks are marked with the synchronized keyword in Java. Keep in mind that only one thread executes the blocks at a time if multiple blocks use the same monitor object. Other threads must wait until the block is exited.

Synchronized Block's General Form

This is a general form of a Synchronized block-

synchronized(sync_object)
{
  // Access shared variables and other shared resources
}

Example

Here is a Java example showing how synchronized blocks work-

class Counter {
    private int c = 0; // Shared variable

    // Method with synchronization block
    public void inc() {
        synchronized(this) { // Synchronize only this block
            c++;
        }
    }

    // Method to get counter value
    public int get() {
        return c;
    }
}

public class igm {
    public static void main(String[] args) {
        Counter cnt = new Counter(); // Shared resource

        // Thread 1 to increment counter
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                cnt.inc();
            }
        });

        // Thread 2 to increment counter
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                cnt.inc();
            }
        });

        // Start both threads
        t1.start();
        t2.start();

        // Wait for threads to finish
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Print final counter value
        System.out.println("Counter: " + cnt.get());
    }
}

Output

This is what the expected output would look like-

Counter: 2000

Related Article: Data Types in Java

Different Types of Synchronizations in Java

I have explained the two types of synchronization in Java with examples to help you understand better-

Types of Synchronizations

1. Process Synchronization

Process synchronization coordinates multiple processes to safely share resources and keep execution in order. Here is an example-

class BankAccount {
    private int balance = 1000; // Shared resource (bank balance)

    // Synchronized method for deposit operation
    public synchronized void deposit(int amount) {
        balance += amount;
        System.out.println("Deposited: " + amount + ", Balance: " + balance);
    }

    // Synchronized method for withdrawal operation
    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdrawn: " + amount + ", Balance: " + balance);
        } else {
            System.out.println("Insufficient balance to withdraw: " + amount);
        }
    }

    public int getBalance() { 
        return balance; 
    }
}

// Main class
public class igm {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(); // Shared resource

        // Thread 1 to deposit money into the account
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                account.deposit(200);
                try {
                    Thread.sleep(50); // Simulate some delay
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // Thread 2 to withdraw money from the account
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                account.withdraw(100);
                try {
                    Thread.sleep(100); // Simulate some delay
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // Start both threads
        t1.start();
        t2.start();

        // Wait for threads to finish
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Print final balance
        System.out.println("Final Balance: " + account.getBalance());
    }
}

Output

This is your expected output -

Withdrawn: 100, Balance: 900
Deposited: 200, Balance: 1100
Deposited: 200, Balance: 1300
Withdrawn: 100, Balance: 1200
Deposited: 200, Balance: 1400
Withdrawn: 100, Balance: 1300
Final Balance: 1300

Explanation

Understand the above example through the given explanation-

  • It shows process synchronization through a shared BankAccount object.
  • Two threads run at the same time. One makes a deposit while the other makes a withdrawal.
  • Both withdrawal () and deposit () are synchronized methods.
  • Synchronized makes sure only a single thread can access the balance at a time.
  • It prevents errors when multiple threads try to change the balance at the same time.

Also Explore: Final Keyword in Java

2. Thread Synchronization

Thread synchronization coordinates the order in which threads run in a multithreaded program. It is done in two ways-

  • Mutual Exclusive

Mutual exclusion makes sure that only one thread gets access to a shared resource or critical section at a time. It stops threads from coming in between one another while sharing data.This is achieved through the synchronized keyword. You must take note of the types of mutual exclusion down below-

1. Synchronized block

2. Synchronized method

3. Static synchronization

Example

Here is an example of Mutual exclusive-

public class Counter {
    private int count = 0;

    public void increment() {
        synchronized (this) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }

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

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

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

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

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

        System.out.println("Final count: " + counter.getCount());
    }
}

Output

This is how your output would appear-

Final count: 2000
  • Cooperation

Cooperation in Java means the ability of multiple threads to team up by sharing data. This is important when threads need to share resources securely and perform tasks in specific sequences. Here is an example-

Output

Here is the output for the given example-

public class SimpleCooperation {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Waiting thread: Waiting for notification...");
                    lock.wait();
                    System.out.println("Waiting thread: Notified! Resuming work.");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread notifyingThread = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Notifying thread: About to notify...");
                lock.notify();
                System.out.println("Notifying thread: Notification sent.");
            }
        });

        waitingThread.start();

        // Optional delay to ensure waitingThread is already waiting
        try { 
            Thread.sleep(1000); 
        } catch (InterruptedException e) { 
            /* ignore */ 
        }

        notifyingThread.start();
    }
}

Read Also: 60+ Java Interview Questions and Answers

What is a Volatile Keyword?

The volatile keyword in Java makes sure that all threads see the most updated value of a variable. This prevents threads from using outdated copies stored in their local caches.

How does Volatile Modifier work?

It makes sure that any updates to a variable are immediately visible to all threads. It does not guarantee that operations like cout++ are atomic. This means that such operations can still result in inconsistent values. Keep in mind that it applies only to variables. Here is an example of a Java program demonstrating the volatile keyword-

class Counter {
    private volatile boolean running = true;

    public void stop() {
        running = false;
    }

    public void start() {
        new Thread(() -> {
            while (running) {
                System.out.println("Running...");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println("Stopped.");
        }).start();
    }
}

public class igm {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        counter.start();
        Thread.sleep(600); // Let it run briefly
        counter.stop();    // Then stop the thread
    }
}

Output

This is your output-

Running...
Running...
Running...
Stopped.

Explanation

  • The volatile keyword makes sure that changes to the running variable are immediately visible to all threads.
  • The start () method creates a new thread that repeatedly prints ‘Running' as long as the running variable is true.
  • The loop is slowed by Thread.sleep (200) to simulate work.
  • The main () method pauses briefly, then invokes stop () to set running to false.

Synchronized Vs Volatile

Take a look at the given table to understand what differs between synchronized from volatile.

Features Synchronized Volatile
Applicable It applies only to methods or blocks It applies to variables
Goal Visibility and mutual exclusion Makes sure that changes to variables are visible to all threads
Performance Low High

Conclusion

It is safe to conclude that Java synchronization has an important role in reliable and concurrent programming. You can take it as a traffic controller who makes sure that threads access shared resources one at a time. This results in data integrity and keeping a distance from issues like race conditions.

FAQs: What is Synchronization in Java

Q1. How does the synchronized keyword work in Java?

Synchronized locks a method or block so only one thread can run it at a time. This makes sure that updates are safely shared among threads.

Q2. What is a monitor lock, and how does it work in Java?

Every Java object comes with a built-in lock. When a thread runs a synchronized method or block, it grabs that lock. Other threads wait until the lock is released before they can enter. It makes sure that only one thread runs that code at a time.

Q3. What is Synchronization in Java used for?

The synchronized keyword in Java is used to control access to shared resources, ensuring that only one thread can execute a block or method at a time.

Q4. Why is Synchronization in Java important?

It prevents data inconsistency and ensures thread safety during concurrent execution.

Q5. What are the types of Synchronization in Java?

Synchronization in Java can be implemented using synchronized methods, synchronized blocks, and static synchronization.

About the Author
Author Nehal Sharma
About the Author

Nehal Sharma is a skilled content writer with expertise in Java, mobile development, and data analytics. She transforms complex data into actionable insights and has experience in business intelligence, data science, and Salesforce. She also simplifies technical concepts into clear, engaging content for learners and professionals.

Drop Us a Query
Fields marked * are mandatory
×

Your Shopping Cart


Your shopping cart is empty.