"How would you design a thread-safe singleton in a mobile application? Explain how you would guarantee a single instance under concurrent access, and discuss the trade-offs of your approach."
A singleton ensures that exactly one instance of a class exists and provides a global access point to it. It is commonly used for shared services such as configuration, logging, networking, or caching.
class Service:
_instance = None
Thread safety means multiple threads can access initialization logic without creating multiple instances or corrupting shared state. Without synchronization, two threads may both observe that no instance exists and each create one.
Lazy initialization delays object creation until the first access, which can reduce startup cost. A lock around initialization prevents races, but it also introduces synchronization overhead if used on every access.
with lock:
if instance is None:
instance = Service()
Double-checked locking avoids taking a lock after the singleton has already been initialized. It checks once before locking and again inside the critical section, though correctness depends on language memory model guarantees.
if instance is None:
with lock:
if instance is None:
instance = Service()
Many mobile languages provide safer singleton mechanisms than manual locking. Examples include static initialization guarantees, enum-based singletons, or language-level lazy properties that are already synchronized.