Seven Synchronization Scenarios in Java: Thread‑Safety Analysis with Code Demonstrations
This article explains seven common Java synchronized usage scenarios, analyzes whether each case is thread‑safe, provides detailed code examples and execution results, and offers practical guidance for interview preparation and correct multithreading design.
Introduction
This article introduces seven synchronized method usage scenarios that frequently appear in multithreaded Java programming and interview questions, explaining the thread‑safety of each case and the underlying lock mechanisms.
Scenario 1: Two threads invoke the same object's synchronized method
Analysis: Both threads compete for the same object lock, so they wait for each other and the execution is thread‑safe.
Conclusion: Thread‑safe.
Scenario 2: Two threads invoke synchronized methods on two different objects
Analysis: Each thread holds a separate object lock, so there is no contention and the execution is not thread‑safe.
Conclusion: Not thread‑safe.
Code verification
public class Condition2 implements Runnable {
// create two different objects
static Condition2 instance1 = new Condition2();
static Condition2 instance2 = new Condition2();
@Override
public void run() {
method();
}
private synchronized void method() {
System.out.println("Thread name: " + Thread.currentThread().getName() + ", start");
try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread: " + Thread.currentThread().getName() + ", end");
}
public static void main(String[] args) {
Thread thread1 = new Thread(instance1);
Thread thread2 = new Thread(instance2);
thread1.start();
thread2.start();
while (thread1.isAlive() || thread2.isAlive()) {}
System.out.println("Test finished");
}
}Execution result
Both threads run in parallel, therefore the scenario is not thread‑safe.
Thread name: Thread-0, start
Thread name: Thread-1, start
Thread: Thread-0, end
Thread: Thread-1, end
Test finishedScenario 3: Two threads invoke a static synchronized method (on one or two objects)
Using a class‑level lock solves the problem of Scenario 2; all threads compete for the same lock, making the execution thread‑safe.
Conclusion: Thread‑safe.
Scenario 4: One thread invokes a synchronized method while another invokes a non‑synchronized method
The non‑synchronized method is not affected by the lock, so the execution is not thread‑safe.
Conclusion: Not thread‑safe.
public class Condition4 implements Runnable {
static Condition4 instance = new Condition4();
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
method0(); // synchronized
}
if (Thread.currentThread().getName().equals("Thread-1")) {
method1(); // non‑synchronized
}
}
private synchronized void method0() { /* ... */ }
private void method1() { /* ... */ }
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {}
System.out.println("Test finished");
}
}Scenario 5: A synchronized method calls a non‑synchronized method
If the non‑synchronized method is called only from the synchronized method, the scenario can be thread‑safe; however, if any other thread calls the non‑synchronized method directly, thread‑safety is lost.
Conclusion: Thread‑safe only when the non‑synchronized method is never invoked directly by other threads.
public class Condition8 implements Runnable {
static Condition8 instance = new Condition8();
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
method2(); // direct call to non‑synchronized method
} else {
method1(); // synchronized method that calls method2()
}
}
private static synchronized void method1() { /* ... */ method2(); }
private static void method2() { /* ... */ }
public static void main(String[] args) { /* start three threads */ }
}Scenario 6: Two threads invoke different synchronized methods on the same object
Both methods share the same object lock, so the execution is serialized and thread‑safe.
Conclusion: Thread‑safe.
public class Condition5 implements Runnable {
static Condition5 instance = new Condition5();
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) method0();
if (Thread.currentThread().getName().equals("Thread-1")) method1();
}
private synchronized void method0() { /* ... */ }
private synchronized void method1() { /* ... */ }
public static void main(String[] args) { /* start two threads */ }
}Scenario 7: One thread invokes a static synchronized method while another invokes a non‑static synchronized method
The static method uses a class‑level lock (Class object), whereas the non‑static method uses an instance lock (this). Since the locks differ, the threads run concurrently and the scenario is not thread‑safe.
Conclusion: Not thread‑safe.
public class Condition6 implements Runnable {
static Condition6 instance = new Condition6();
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) method0(); // static synchronized
if (Thread.currentThread().getName().equals("Thread-1")) method1(); // instance synchronized
}
private static synchronized void method0() { /* ... */ }
private synchronized void method1() { /* ... */ }
public static void main(String[] args) { /* start two threads */ }
}Scenario 8: Synchronized method throws an exception
When a synchronized method exits abruptly due to an exception, the JVM automatically releases the lock, allowing other threads to acquire it without deadlock.
Conclusion: The lock is released on normal exit or exception, so the scenario remains thread‑safe.
public class Condition7 implements Runnable {
private static Condition7 instance = new Condition7();
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) method0(); // throws
if (Thread.currentThread().getName().equals("Thread-1")) method1(); // normal
}
private synchronized void method0() { /* ... */ throw new RuntimeException(); }
private synchronized void method1() { /* ... */ }
public static void main(String[] args) { /* start two threads */ }
}Summary
The article systematically demonstrates the behavior of the synchronized keyword in eight typical Java multithreading scenarios, explains the lock objects involved (object lock, class lock, re‑entrancy), and provides clear conclusions on thread‑safety, which are essential knowledge for Java developers and interview preparation.
Source: blog.csdn.net/x541211190/article/details/106272922
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
