Join our Newsletter — 33% off our NHI Course
Home› Glossary› AI Security› Double-checked locking
AI Security

Double-checked locking

← Back to Glossary
By NHI Mgmt Group Updated October 31, 2026 Domain: AI Security

Double-checked locking is a lazy initialisation pattern that tries to avoid synchronizing every call by checking a value before and after a lock. It is only safe when publication is correctly ordered, which is why missing memory visibility guarantees can expose partially constructed objects.

How double-checked locking works

Double-checked locking is a performance pattern for lazy initialisation. The first check avoids unnecessary locking after the object has already been created, while the second check inside the critical section prevents duplicate construction when multiple threads race to initialise the same value. Its appeal is reduced contention, not stronger correctness by itself.

The pattern is easiest to understand as a compromise between eager initialisation and coarse locking. It tries to make the common path fast, but that only works if the language runtime and memory model guarantee that other threads will not observe a partially published object. Without those guarantees, the optimisation can become a correctness bug rather than a performance improvement.

Why publication order matters

The central issue is safe publication. Initialisation is not just about constructing an object, it is also about making its state visible to other threads in the right order. If writes to fields, references, or internal caches are reordered or observed out of sequence, another thread may see a non-null reference before the object is fully ready for use.

This is why the pattern is closely tied to memory visibility guarantees, not just mutual exclusion. Locking one path does not automatically make every read safe if the fast path can bypass the lock. In practice, double-checked locking only works when the underlying implementation provides the necessary happens-before relationship or equivalent publication discipline.

Where the pattern is used

Developers typically reach for double-checked locking when a resource is expensive to create but needed only once, such as a cache, registry, parser, or shared helper. The pattern can be useful when start-up cost matters and the object has a long lifetime, because the locked path is paid only during first use.

That said, the term is often used as shorthand for a broader family of lazy initialisation approaches. Some variants are safe in one language and unsafe in another, and some are only safe when the variable is declared or published with the correct memory semantics. The practical lesson is that the pattern’s safety depends on the runtime contract, not on the code shape alone.

Common failure mode and safer alternatives

The classic failure mode is partial construction: one thread creates the object, but another thread observes it before construction has fully completed. The result can be intermittent crashes, stale fields, null dereferences, or logic that behaves inconsistently under load, which makes the bug hard to reproduce and easy to misdiagnose.

Safer alternatives often avoid the need for a hand-written race entirely. Depending on the language, that may mean eager initialisation, static initialisation, a guaranteed thread-safe lazy helper, or a publication mechanism with explicit memory semantics. The right choice is usually the one that makes correctness obvious rather than relying on subtle ordering assumptions.

Risk and Threat Considerations

Double-checked locking can create a hidden reliability risk because the code may appear thread-safe while still allowing unsafe publication. When the pattern is implemented without the required memory barriers or language guarantees, failures often surface only under concurrency, high load, or specific CPU scheduling behaviour.

Failure mechanism: A thread reads the shared reference after the first check but before the object’s construction has been fully published, so it observes incomplete internal state.

Impact: The resulting bug can corrupt application logic, trigger intermittent crashes, or expose inconsistent behaviour that is difficult to detect in testing and expensive to debug in production.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

NIST SP 800-53 Rev 5, NIST CSF 2.0 and OWASP ASVS set the technical controls, while ISO/IEC 27001:2022 defines the regulatory obligations.

FrameworkControl / ReferenceRelevance
NIST SP 800-53 Rev 5SI-7 — Software, Firmware, and Information IntegrityConcurrency bugs can undermine trusted runtime state and integrity assumptions.
Recommendation — Validate runtime integrity assumptions and catch unsafe object publication in code review and testing.
NIST CSF 2.0PR.DS-06 — Integrity is protectedSafe publication preserves integrity of shared program state across threads.
Recommendation — Protect shared state integrity by using thread-safe lazy initialisation primitives.
OWASP ASVSV15 — Secure Coding and ArchitectureThe pattern is a code-level concurrency design choice that affects correctness and secure architecture.
Recommendation — Prefer runtime-provided safe lazy loading and avoid ad hoc concurrency primitives for shared objects.
ISO/IEC 27001:2022A.8.28 — Secure codingImplementing the pattern safely depends on secure code design and correct memory handling.
Recommendation — Apply secure coding review to concurrency patterns that depend on memory ordering.

Practitioner Guidance

Why practitioners should care: Treat double-checked locking as a correctness-sensitive optimisation, not a default concurrency pattern. If the language or platform offers a built-in thread-safe lazy mechanism, that is usually easier to reason about and maintain.

What to watch for: Review whether the shared value is published with the correct memory semantics for the runtime in use. If the answer depends on subtle implementation details, the pattern is probably too fragile for long-term maintenance.

Practitioner takeaway: Use double-checked locking only when you can prove safe publication, because the performance gain is not worth a race that appears rarely and fails unpredictably.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Reviewed and updated by the NHIMG editorial team on October 31, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org