Fundamentals 7 min read

How SLF4J Implements Double‑Checked Locking: A Deep Dive into Singleton Initialization

This article examines SLF4J's source code to explain how the framework uses a double‑checked locking pattern with a volatile provider field to safely initialize its LoggerFactory, detailing each step, the underlying Java memory model issues, and a classic singleton example.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
How SLF4J Implements Double‑Checked Locking: A Deep Dive into Singleton Initialization

Getting a Logger

Typical usage obtains a logger via:

Logger logger = LoggerFactory.getLogger(NoBindingTest.class);

Calling LoggerFactory.getLogger first obtains an ILoggerFactory instance. The factory is provided by SLF4JServiceProvider, whose initialization uses a double‑checked locking pattern.

Double‑Checked Locking in getProvider

static SLF4JServiceProvider getProvider() {
    if (INITIALIZATION_STATE == UNINITIALIZED) {
        synchronized (LoggerFactory.class) {
            if (INITIALIZATION_STATE == UNINITIALIZED) {
                INITIALIZATION_STATE = ONGOING_INITIALIZATION;
                performInitialization();
            }
        }
    }
    switch (INITIALIZATION_STATE) {
        case SUCCESSFUL_INITIALIZATION: return PROVIDER;
        case NOP_FALLBACK_INITIALIZATION: return NOP_FALLBACK_FACTORY;
        case FAILED_INITIALIZATION: throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
        case ONGOING_INITIALIZATION: return SUBST_PROVIDER;
    }
    throw new IllegalStateException("Unreachable code");
}

The method first checks whether initialization is required. If so, it synchronizes on LoggerFactory.class, checks the condition again, and then performs the actual initialization. Subsequent calls find the state already initialized and skip the synchronized block, improving concurrency.

Why Double‑Check?

Synchronizing the whole method would add a lock on every call, which is unnecessary because initialization happens only once. The double‑check narrows the lock to the first invocation.

If two threads enter the first if simultaneously, both see UNINITIALIZED. The synchronized block ensures that only one thread proceeds to initialize; the other waits, then sees the updated state and returns the already‑initialized provider.

Singleton Pattern Example

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

The example mirrors SLF4J’s approach. The volatile keyword guarantees visibility of the fully constructed object across threads and prevents instruction reordering that could expose a partially constructed instance.

Without volatile, the JVM might reorder the steps of object allocation (memory allocation → constructor execution → reference assignment). Another thread could observe a non‑null reference before the constructor finishes, leading to NullPointerException or other bugs.

Volatile Provider Field in SLF4J

static volatile SLF4JServiceProvider PROVIDER;

SLF4J marks the provider with volatile for the same reasons: to ensure that once initialization completes, all threads see the correctly constructed provider instance.

Summary

SLF4J applies the classic double‑checked locking pattern to lazily initialize its service provider. The pattern relies on a volatile field, a two‑step condition check, and a synchronized block that runs only during the first initialization, providing thread‑safe lazy singleton creation without the performance cost of full‑method synchronization.

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.

volatileslf4jJava concurrencysingleton patterndouble-checked lockinglogging framework
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

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.