Understanding iOS Singleton Implementation and the dispatch_once Mechanism

This article explains how the iOS singleton pattern works, why dispatch_once executes only once during an app's lifecycle, examines the underlying GCD source code, shows how to manually reset a singleton, and discusses the thread‑safety guarantees of the implementation.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding iOS Singleton Implementation and the dispatch_once Mechanism

The singleton pattern is frequently used in iOS development, but many developers wonder why its initialization runs only once, what low‑level mechanisms enable this behavior, and whether a singleton can be destroyed.

Using dispatch_once_t and a block, the runtime guarantees a single execution. Example code:

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ class = [[self alloc] init]; });

The two crucial parameters are the onceToken and the block. The core logic is that the static token is wrapped into a dispatch_once_gate_t which provides an atomic state variable. When the state equals DLOCK_ONCE_DONE, the function returns immediately; otherwise the first thread acquires a lock, runs the block, and then marks the state as done.

The underlying GCD functions are:

void dispatch_once(dispatch_once_t *val, dispatch_block_t block) {
    dispatch_once_f(val, block, _dispatch_Block_invoke(block));
}

and the more detailed implementation dispatch_once_f which performs atomic loads, checks for the done state, tries to acquire a lock via _dispatch_once_gate_tryenter, calls the block through _dispatch_once_callout, and finally broadcasts the completion.

To “destroy” a singleton, the article modifies the implementation by resetting the predicate value before calling dispatch_once:

static SMObject *class = nil;
static dispatch_once_t predicate;
NSLog(@"1:%ld", predicate);
predicate = 0;
dispatch_once(&predicate, ^{ class = [[SMObject alloc] init]; });

By setting predicate back to zero, each call re‑initializes the object, effectively allowing multiple creations. A corresponding deallocSM method resets both the predicate and the stored instance.

Thread safety is ensured by the atomic compare‑and‑swap operation in _dispatch_once_gate_tryenter, which uses os_atomic_cmpxchg to lock the gate only for the first thread, preventing concurrent executions of the block.

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.

iOSconcurrencySingletonObjective‑Cdispatch_once
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

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.