Why Using synchronized on a Local Variable Fails to Lock in Java Multithreading

The article demonstrates that synchronizing on a locally created object does not provide proper thread safety, shows the resulting chaotic output, and explains how moving the lock object to a class field resolves the issue, illustrated with Java code and debugging screenshots.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Why Using synchronized on a Local Variable Fails to Lock in Java Multithreading

During a code review the author discovered a Java senior engineer mistakenly used synchronized on a locally created object, believing it would protect shared data across threads.

The original program creates two threads that both execute MyThread.run(), where a new Object is instantiated inside the method and used as the monitor:

package com.sample.interview.multithread;

public class SynchronizedTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread, "线程1");
        Thread t2 = new Thread(myThread, "线程2");
        t1.start();
        t2.start();
    }
}

class MyThread implements Runnable {
    private static int count = 0;

    @Override
    public void run() {
        Object obj = new Object();
        synchronized (obj) {
            for (int i = 0; i < 3; i++) {
                System.out.println("当前线程:" + Thread.currentThread().getName() + ",数值为:" + (count++));
            }
        }
    }
}

Because each thread creates its own obj, the two monitors are different, so the synchronized block does not serialize the execution. The sample output shows interleaved prints from both threads, e.g.:

当前线程:线程2,数值为:1
当前线程:线程1,数值为:0
当前线程:线程2,数值为:2
当前线程:线程1,数值为:3
当前线程:线程2,数值为:4
当前线程:线程1,数值为:5

The article then modifies the code by making the lock object a class‑level static field (instead of a local variable). After this change the output becomes ordered, confirming that the threads now contend for the same monitor:

当前线程:线程1,数值为:0
当前线程:线程1,数值为:1
当前线程:线程1,数值为:2
当前线程:线程2,数值为:3
当前线程:线程2,数值为:4
当前线程:线程2,数值为:5

Debugging screenshots illustrate the thread states: one thread is RUNNING while the other is in the MONITOR (blocked) state, waiting for the lock to be released. The conclusion is that synchronizing on a local variable does not provide mutual exclusion; the lock must be a shared object, typically a field, to be effective.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

debuggingjavalockingsynchronized
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.