Mastering Thread Safety in Java: When and How to Use synchronized

Thread safety issues arise when multiple threads access shared resources like variables, objects, or databases, potentially causing duplicate data or errors; this article explains when such problems occur and demonstrates how Java’s synchronized methods, synchronized blocks, and lock mechanisms can ensure safe, serialized access.

21CTO
21CTO
21CTO
Mastering Thread Safety in Java: When and How to Use synchronized

Although multithreaded programming greatly improves efficiency, it can introduce hidden risks such as duplicate data insertion when two threads write to the same database table simultaneously.

When does thread safety issue occur?

In single‑threaded programs there is no thread‑safety problem. In multithreaded scenarios, multiple threads may access the same resource—variables, objects, files, or database tables—at the same time, leading to results that differ from the intended behavior or cause runtime errors.

For example, two threads reading data from the network and inserting it into a table that must not contain duplicates will each perform two operations: (1) check whether the data already exists, and (2) insert if it does not. If both threads read the same data before either inserts it, they may both decide the data is absent and insert it, resulting in duplicate rows. The shared resource in this case is called a critical (or shared) resource .

How to solve thread safety issues?

All concurrency patterns solve thread‑safety by serializing access to the critical resource , i.e., allowing only one thread to use the resource at a time. This is achieved by placing a lock before the critical code and releasing it afterward.

In Java, two primary mechanisms provide this mutual‑exclusion: the synchronized keyword and the Lock interface (the latter is covered in another article).

synchronized methods or blocks

Every Java object has an associated monitor (lock). When a thread enters a synchronized method or block, it acquires the object's monitor; other threads must wait until the lock is released.

synchronized method

The following example shows two threads invoking insert on the same InsertData instance without synchronization, which leads to interleaved execution:

public class Test {
    public static void main(String[] args) {
        final InsertData insertData = new InsertData();
        new Thread() {
            public void run() {
                insertData.insert(Thread.currentThread());
            }
        }.start();
        new Thread() {
            public void run() {
                insertData.insert(Thread.currentThread());
            }
        }.start();
    }
}

class InsertData {
    private java.util.ArrayList<Integer> arrayList = new java.util.ArrayList<Integer>();
    public void insert(Thread thread) {
        for (int i = 0; i < 5; i++) {
            System.out.println(thread.getName() + " inserting data " + i);
            arrayList.add(i);
        }
    }
}

Running this code shows both threads executing insert concurrently.

Adding the synchronized modifier to the method forces the threads to execute sequentially:

public class InsertData {
    private java.util.ArrayList<Integer> arrayList = new java.util.ArrayList<Integer>();
    public synchronized void insert(Thread thread) {
        for (int i = 0; i < 5; i++) {
            System.out.println(thread.getName() + " inserting data " + i);
            arrayList.add(i);
        }
    }
}

Output confirms that Thread‑1 starts inserting only after Thread‑0 finishes.

Important points:

When a thread holds an object's lock, no other thread can enter any synchronized method of that same object.

Non‑synchronized methods do not require the lock and can be invoked concurrently.

Locks are per‑object; two threads synchronizing on different instances do not block each other.

synchronized block

A synchronized block lets you lock on any object, offering finer granularity than a synchronized method:

public void insert(Thread thread) {
    synchronized (this) {
        for (int i = 0; i < 100; i++) {
            System.out.println(thread.getName() + " inserting data " + i);
            arrayList.add(i);
        }
    }
}

Or using a dedicated lock object:

private final Object lock = new Object();
public void insert(Thread thread) {
    synchronized (lock) {
        // critical section
    }
}

Blocks are more flexible because only the code that truly needs protection is synchronized, improving performance.

Static synchronization vs. instance synchronization

Each class also has a class‑level lock used for static synchronized methods. An instance lock and a class lock are independent, so a thread executing a non‑static synchronized method does not block another thread executing a static synchronized method of the same class.

Bytecode inspection shows that a synchronized block compiles to monitorenter and monitorexit instructions, while a synchronized method carries the ACC_SYNCHRONIZED flag, causing the JVM to acquire and release the appropriate lock automatically. If an exception occurs inside a synchronized region, the JVM still releases the lock, preventing deadlocks.

Reference materials:

《Java编程思想》

http://ifeve.com/synchronized-blocks/

http://ifeve.com/java-synchronized/

http://blog.csdn.net/ns_code/article/details/17199201

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.

Javathread safetymultithreadingsynchronized
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

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.