Backend Development 13 min read

Understanding Stateful vs. Stateless Beans, Singleton vs. Prototype Scope, and Thread Safety in Spring

This article explains the differences between stateful and stateless Spring beans, the impact of singleton and prototype scopes on thread safety, and demonstrates how ThreadLocal can be used to safely share resources in multithreaded backend applications, complete with code examples.

Top Architect
Top Architect
Top Architect
Understanding Stateful vs. Stateless Beans, Singleton vs. Prototype Scope, and Thread Safety in Spring

Hello, I am a senior architect.

1. Stateful Bean and Stateless Bean

Stateful bean: Each user gets a unique instance that holds user-specific data during the user’s lifecycle; the bean’s state is tied to the user.

Stateless bean: The bean instance is placed in a shared pool and can be used by multiple users; it does not retain user-specific state unless it has its own fields.

In Spring bean configuration, the two common scopes are singleton (one instance per container) and prototype (a new instance each injection). Example configuration:

<bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" />
<bean id="testManager" class="com.sw.TestManagerImpl" scope="prototype" />

When a bean is configured as singleton and holds mutable state (e.g., a User field), concurrent requests can overwrite each other's data, leading to thread‑safety problems. Using prototype avoids this sharing.

public class TestManagerImpl implements TestManager {
    private User user;
    public void deleteUser(User e) throws Exception {
        user = e; // step 1
        prepareData(e);
    }
    public void prepareData(User e) throws Exception {
        user = getUserByID(e.getId()); // step 2
        // use user.getId(); // step 3
    }
}

2. Singleton in Spring

Spring’s singleton differs from the classic design‑pattern singleton: it is a single instance per IoC container, not per JVM. Because singleton beans are shared, mutable member variables can cause concurrency issues. Solutions include using method‑local variables, ThreadLocal , or changing the bean scope to prototype .

3. Using ThreadLocal to Solve Thread‑Safety Issues

Spring does not automatically make beans thread‑safe; developers must handle mutable state. A typical example is a DAO that holds a non‑thread‑safe Connection . By storing the connection in a ThreadLocal , each thread gets its own instance:

public class TopicDao {
    // ① non‑thread‑safe variable
    private Connection conn;
    public void addTopic() {
        Statement stat = conn.createStatement();
    }
}
public class TopicDao {
    // ① ThreadLocal to hold Connection per thread
    private static ThreadLocal
connThreadLocal = new ThreadLocal<>();
    public static Connection getConnection() {
        if (connThreadLocal.get() == null) {
            Connection conn = createConnection();
            connThreadLocal.set(conn);
            return conn;
        }
        return connThreadLocal.get();
    }
    public void addTopic() {
        try {
            Statement stat = getConnection().createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

With this approach, the DAO can remain a singleton while each thread works with its own connection, preserving thread safety.

4. Comparison Between ThreadLocal and Synchronized Mechanisms

Both ThreadLocal and synchronized blocks aim to resolve concurrent access conflicts. Synchronization uses a lock so only one thread can access the shared variable at a time, requiring careful design to avoid deadlocks. ThreadLocal gives each thread an independent copy of the variable, eliminating the need for locking and often resulting in higher concurrency.

In summary, ThreadLocal provides a space‑for‑time trade‑off: each thread holds its own data, allowing simultaneous access without contention, whereas traditional synchronization trades time for a single shared copy.

References

Discussion on Spring thread safety

How Spring handles concurrent access

Spring’s approach to ensuring thread safety

Why Spring’s singleton Service and DAO can be thread‑safe

JavaSpringThread SafetythreadlocalBean Scope
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.