Java
Multithreading
Synchronized
Concurrency
Thread Safety

How can two threads be in a synchronized method

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

At first glance, it seems impossible for two Java threads to be inside a synchronized method at the same time. The key is that synchronized locks a monitor object, not a method name globally. Two threads can run synchronized code concurrently when they lock different monitors.

Instance Synchronized Locks this

For instance methods, the lock is the current object instance.

java
1class Counter {
2    public synchronized void inc() {
3        System.out.println(Thread.currentThread().getName());
4    }
5}

If two threads call inc on the same Counter object, one must wait.

Different Instances Mean Different Locks

If each thread uses a different object instance, each thread locks a different monitor.

java
1Counter a = new Counter();
2Counter b = new Counter();
3
4new Thread(a::inc, "T1").start();
5new Thread(b::inc, "T2").start();

Both threads can execute concurrently even though method definition is identical.

Static Synchronized Uses Class Monitor

Static synchronized methods lock the Class object, not an instance.

java
1class Service {
2    public static synchronized void syncStatic() {
3        System.out.println(Thread.currentThread().getName());
4    }
5}

All calls to that static method share one class-level lock.

Instance and Static Locks Can Run Together

One thread can execute an instance synchronized method while another executes a static synchronized method of same class, because monitors differ:

  • instance method monitor: object instance
  • static method monitor: class object

This often explains surprising concurrency observations.

Reentrancy Is Not Parallel Access

Java intrinsic locks are reentrant. Same thread may enter synchronized code guarded by the same monitor again.

java
1class ReentrantDemo {
2    public synchronized void outer() { inner(); }
3    public synchronized void inner() { }
4}

This is one thread re-entering, not two threads bypassing synchronization.

Explicit Lock Objects

Code can synchronize on custom lock objects instead of this.

java
1class Store {
2    private final Object lock = new Object();
3
4    void update() {
5        synchronized (lock) {
6            // critical section
7        }
8    }
9}

This is useful for controlling lock visibility and separating independent critical sections.

Why Bugs Still Happen with synchronized

Synchronization fails to protect state when different code paths lock different objects while touching same data. Example problems:

  • one method synchronized on this
  • another synchronized on separate helper object
  • shared state modified in both paths

Mutual exclusion exists per lock, not per variable.

Debugging Strategy

When behavior seems impossible:

  1. identify exact lock object in each code path
  2. verify whether threads share same instance
  3. check static versus instance mismatch
  4. inspect thread dump for monitor ownership

Thread dumps and profiler lock views are much more useful than reading method signatures alone.

Practical Design Guidance

Use a clear lock strategy per shared state region and document it. If concurrency requirements grow, higher-level constructs such as ReentrantLock, ReadWriteLock, or concurrent collections may be clearer than scattered synchronized blocks.

Consistency of lock strategy matters more than the specific primitive.

Demonstration with Competing Locks

A useful teaching test is creating two synchronized methods that lock different objects and printing timestamps from each thread. Seeing both outputs interleave confirms that lock identity, not method keyword alone, determines mutual exclusion. This experiment helps teams internalize monitor semantics quickly.

Shared Lock Documentation

Document lock ownership near shared mutable fields so future maintainers do not introduce alternate lock paths accidentally. Clear ownership notes prevent many latent concurrency defects.

Common Pitfalls

  • Assuming synchronized creates one global lock for a method name.
  • Forgetting each object instance has its own monitor.
  • Mixing static and instance synchronization unintentionally.
  • Synchronizing on different locks for same shared state.
  • Confusing reentrant same-thread execution with multi-thread lock bypass.

Summary

  • 'synchronized is monitor-based, not globally method-based.'
  • Instance synchronized methods lock object instances.
  • Static synchronized methods lock class object.
  • Two threads can run synchronized code concurrently if lock objects differ.
  • Correct thread safety depends on consistent lock ownership for shared state.

Course illustration
Course illustration

All Rights Reserved.