Java synchronized Keyword
Usage and Examples

synchronized Keyword in Java

The synchronized keyword in Java is a powerful tool used to control access to critical sections of code when multiple threads are involved. It ensures that only one thread can access a block or method at a time, helping to avoid thread interference and memory consistency issues.

Why Synchronization Is Needed

In a multi-threaded environment, when multiple threads try to modify shared data simultaneously, unexpected results can occur. This is called a race condition. Synchronization provides a mechanism to prevent race conditions by allowing only one thread to access a critical section at a time.

Types of Synchronization

  • Method Synchronization – Using synchronized in method declarations
  • Block Synchronization – Synchronizing a specific portion of code inside a method
  • Static Synchronization – Synchronizing static methods, which lock on the class object

1. Synchronized Instance Method

A synchronized instance method locks the current object (i.e., this) so that only one thread at a time can execute any of its synchronized methods.

class Counter {
  private int count = 0;

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

  public int getCount() {
    return count;
  }
}

Explanation:

Here, the increment() method is synchronized. If two threads try to call it at the same time on the same object, only one will succeed at a time.

2. Synchronized Block

Use synchronized blocks when you want to synchronize only a portion of the method instead of the entire method. This gives better performance by reducing lock scope.

class Printer {
  public void printDoc(String docName) {
    synchronized(this) {
      System.out.println("Printing: " + docName);
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("Done Printing: " + docName);
    }
  }
}

Explanation:

The synchronized(this) block ensures that only one thread can print a document at a time using the same Printer object.

3. Synchronized Static Method

When you declare a static method as synchronized, the lock is applied on the class object, not the instance.

class Logger {
  public static synchronized void log(String msg) {
    System.out.println("Logging: " + msg);
  }
}

Explanation:

If multiple threads call Logger.log() at the same time, only one can execute it at a time, regardless of instance.

Real-World Example: Bank Account

This example shows how synchronization can prevent inconsistencies when multiple threads try to deposit money into a shared bank account.

class BankAccount {
  private int balance = 0;

  public synchronized void deposit(int amount) {
    balance += amount;
  }

  public int getBalance() {
    return balance;
  }
}

public class Main {
  public static void main(String[] args) throws InterruptedException {
    BankAccount account = new BankAccount();

    Thread t1 = new Thread(() -> {
      for (int i = 0; i < 1000; i++) account.deposit(1);
    });

    Thread t2 = new Thread(() -> {
      for (int i = 0; i < 1000; i++) account.deposit(1);
    });

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

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

    System.out.println("Final balance: " + account.getBalance());
  }
}
Final balance: 2000

Without Synchronization

If we remove the synchronized keyword from the deposit() method, the output may vary:

Final balance: 1724  (or some other incorrect number)

Do's and Don'ts

  • Use synchronized to protect shared resources
  • Use block synchronization to improve performance
  • Don't overuse synchronization; it can lead to deadlocks and performance issues
  • Avoid synchronizing on publicly accessible objects (like strings)

Common Interview Questions

  • What is the purpose of the synchronized keyword?
  • What’s the difference between synchronized method and synchronized block?
  • What happens if two threads call a synchronized method on different objects?
  • What is the difference between object lock and class lock in Java?