0
0
JavaHow-ToBeginner · 3 min read

How to Use synchronized Keyword in Java for Thread Safety

In Java, the synchronized keyword is used to control access to a block of code or method so that only one thread can execute it at a time. It helps prevent problems when multiple threads try to change shared data simultaneously by locking the object or class during execution.
📐

Syntax

The synchronized keyword can be used in two main ways: to lock an entire method or to lock a specific block of code inside a method.

  • Synchronized method: Locks the entire method for the current object or class.
  • Synchronized block: Locks a specific object for the code inside the block.
java
public synchronized void methodName() {
    // code that only one thread can run at a time
}

// or

public void methodName() {
    synchronized(lockObject) {
        // code that only one thread can run at a time
    }
}
💻

Example

This example shows two threads trying to increase a shared counter. Using synchronized on the method ensures only one thread updates the counter at a time, preventing errors.

java
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        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
Final count: 2000
⚠️

Common Pitfalls

  • Not synchronizing shared data access: Forgetting to use synchronized can cause race conditions where threads interfere with each other.
  • Synchronizing on wrong object: Locking on different objects does not prevent concurrent access properly.
  • Using synchronized too broadly: Locking large code blocks or entire methods unnecessarily can reduce performance.
  • Deadlocks: Improper locking order between multiple locks can cause threads to wait forever.
java
public class WrongLock {
    private int count = 0;
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    // Wrong: locking on different objects in different methods
    public void increment() {
        synchronized(lock1) {
            count++;
        }
    }

    public void decrement() {
        synchronized(lock2) {
            count--;
        }
    }
}
📊

Quick Reference

  • synchronized method: Locks the current object (or class if static).
  • synchronized block: Locks a specified object only for the block.
  • Use for: Protecting shared mutable data in multithreaded code.
  • Avoid: Holding locks too long or locking unrelated code.

Key Takeaways

Use synchronized to allow only one thread at a time to run critical code.
Synchronize on the correct object to ensure proper locking.
Avoid locking large code sections to keep performance good.
Always protect shared mutable data when accessed by multiple threads.
Be careful to prevent deadlocks by consistent lock ordering.