What is the Swift equivalent to Objective-C's synchronized?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Swift does not have a direct language feature equivalent to Objective-C's @synchronized block. Instead, Swift offers several concurrency tools, and the best replacement depends on whether you are protecting shared mutable state in legacy code, coordinating work on a queue, or using the modern actor-based concurrency model.
What @synchronized Did in Objective-C
In Objective-C, @synchronized wrapped a critical section and locked on an object reference. It was convenient because the lock and unlock behavior was automatic, but it also hid some complexity and overhead.
If you are migrating old code, the first question is not "what is the Swift syntax equivalent?" but "what concurrency model should this code use now?"
Use NSLock for Direct Mutual Exclusion
When you need a straightforward lock around shared state in synchronous code, NSLock is the closest conceptual replacement.
Using defer is important because it guarantees unlock even if the method exits early.
Use a Serial DispatchQueue for Ownership-Style Access
If you want all access to a piece of state to happen on one queue, a private serial queue is often cleaner than explicit lock management.
This reads well and avoids manual lock bookkeeping, though you still need to think carefully about reentrancy and calling sync from the same queue.
Prefer Actors in Modern Swift Concurrency
For new Swift code, actors are usually the best high-level replacement because they isolate mutable state by design.
With actors, you do not manually lock and unlock. The compiler and runtime enforce access rules around actor-isolated state, which removes an entire class of mistakes common with traditional locking.
Choose Based on Code Style and Constraints
A practical guideline is:
- use
NSLockwhen integrating with older synchronous code paths - use a serial queue when queue ownership already fits the design
- use actors for new async-capable Swift code
There is no single universal replacement because @synchronized bundled several concerns into one easy syntax, while Swift encourages more explicit architectural choices.
Avoid Translating Patterns Blindly
Directly translating every @synchronized block into a lock in Swift can preserve old design problems. Sometimes the better migration is to remove shared mutable state entirely, or to isolate it behind an actor or dedicated queue-based component.
That usually leads to code that is easier to reason about, test, and evolve.
Common Pitfalls
- Locking with
NSLockbut forgettingdefer, which can leave the lock held on early return or failure. - Calling
syncrecursively on the same serial queue and causing a deadlock. - Assuming actors are a drop-in replacement for every synchronous API shape.
- Translating Objective-C locking patterns mechanically instead of redesigning around Swift concurrency.
- Protecting only writes while leaving reads unsynchronized.
Summary
- Swift has no exact syntax equivalent to Objective-C's
@synchronized. - '
NSLockis the closest direct mutual-exclusion replacement.' - Serial
DispatchQueueaccess is often cleaner when one queue should own the state. - Actors are usually the best option for new Swift concurrency code.
- Choose the tool based on the code's architecture, not on syntax similarity alone.

