AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 22–28 January 2025

Choose Swift synchronization by the access contract

Choose Swift locks and actors by access needs, suspension and state invariants. A small benchmark cannot decide how an application should coordinate work.

Citiți articolul în română

Choose a Swift synchronization mechanism by what callers must be allowed to do. A short synchronous update protected by a lock and an operation isolated to an actor provide different contracts. Treating them as interchangeable entries in a speed table can change the application's behavior before it improves performance.

Looking back from November 2026, the useful question in the January discussion is how long an assumption about shared state remains valid. That question connects directly to delivery risk: an application can avoid a data race and still make the wrong business decision because its state changed while an operation was suspended.

Keep the December experiment in December

Jacob Bartlett's Synchronization framework article displays 30 December 2024. It compares concurrency primitives through his experiments. The January community discussion revisits that article; it is not the date of a new framework release. Bartlett's measurements belong to his workloads and setup. They were not replicated for this article and do not establish a universal performance ranking.

The enduring design issue is independent of any particular timing result. Before comparing implementations, describe the operation that each implementation promises. If one implementation holds exclusive access throughout a state change while another suspends halfway through a longer operation, the difference is semantic. A faster result does not tell you whether the two versions solve the same problem.

Define the protected transition

Consider an explicitly illustrative in-memory counter used to allocate a local sequence number. The required transition reads the next value, advances it and returns the allocated number. A short critical section can make that transition indivisible with respect to other users of the same lock. Every access to the protected state must follow the same rule.

The caller stays in synchronous code. Acquiring a contended lock may block the executing thread; keeping the section short matters. Network calls, disk access and arbitrary callbacks make its duration harder to bound. A callback can also re-enter code that wants the same lock. The design should make those possibilities visible rather than hiding them behind an innocent accessor name.

For this counter, write the promise narrowly: allocation is coordinated inside this process. That does not establish ordering between devices, durability after a crash or uniqueness across several servers. Synchronization protects a defined state boundary. It does not automatically supply the wider product guarantees that a sequence number might suggest to a business owner.

A suspension changes the reasoning

An actor is useful when state belongs to an isolated component whose callers participate in Swift concurrency. Access across its isolation boundary can require asynchronous coordination. Its value is the ownership model as well as the scheduling behavior; it is more than a lock with different spelling.

The Swift actor proposal, a historical design document, explains actor isolation and reentrancy. An actor operation that suspends does not reserve the actor's state unchanged until the operation resumes. Other work can run during that suspension. The current revision of the proposal is explanatory evidence, not a record of every January toolchain detail.

Imagine, as a design example, checking local availability, awaiting a remote confirmation and then recording a reservation. Between the check and the final update, another actor operation may change availability. The code needs a rule for that change: reserve before waiting, revalidate afterward, or represent an intermediate state explicitly. Which rule is correct depends on cancellation, failure and the product's definition of a reservation.

A synchronous actor method without an internal suspension has a different reasoning boundary from that longer workflow. Avoid describing all actor methods as if they necessarily interleave at every statement. The important places to inspect are the suspension points and the assumptions carried across them.

Compare equivalent work before comparing time

A useful performance investigation would first hold the required behavior constant. Specify the number and pattern of callers, contention, work inside the protected region and whether a caller needs a result synchronously. Include the cost of entering the chosen abstraction rather than timing only its most convenient fragment.

Then inspect what users actually experience. If synchronization contributes little to a slow screen, replacing the ownership model may add complexity without helping the delay. If contention is substantial, a smaller protected region or different state layout may matter more than a primitive swap. These are proposed investigation steps, not measurements of an AL+ application.

The strongest argument for actors remains strong even when a tiny synchronous benchmark favors a lock. A stateful component coordinating asynchronous operations may be easier to understand when its ownership is explicit. Reducing the number of places that can touch its state can be worth more than optimizing a very small operation.

Conversely, forcing a genuinely synchronous, bounded state transition into an asynchronous interface can spread coordination costs through callers. The decision should acknowledge both costs. Neither abstraction deserves to become a universal house rule based on one example.

Leave a contract the next developer can use

For iPhone application development, ask for a short statement beside the design: who owns the state, which operations are synchronous, where suspension is permitted and which assumptions must be checked again after waiting. Also state what happens if work is cancelled or a remote dependency fails.

That statement gives a reviewer something more durable than a timing screenshot. It lets the next change be assessed against the application's behavior. Swift 6 migration and compiler checking are separate projects; choosing an access contract is the smaller decision that must remain clear inside them.