Atomic Accessor Locking vs Nonatomic for a Concurrently Read Flag
0 reputation · 09 Jun 2023, 23:34 UTC
0 reputation · 09 Jun 2023, 23:34 UTC
A shared scalar property—such as a feature flag or request counter—is read and written from multiple threads during concurrent request handling. The decision is whether to keep the default synthesized atomic attribute, which wraps each accessor in a lock, or to declare the property nonatomic and remove that per-access locking.
The constraint is that accessor-level locking only guarantees individual getter and setter calls, not read-modify-write sequences or compound invariants. Under concurrent load, contention on the accessor lock may introduce latency that never appears in single-threaded tests, while nonatomic eliminates that lock but leaves multi-step updates unsynchronized. Behavior also varies with the Apple Clang toolchain, runtime, and deployment target, and ARC memory semantics remain separate from the accessor attribute.
Does the default atomic accessor lock protect a compound invariant across multiple calls, or must the property be nonatomic with external synchronization to own that invariant? What synchronization boundary is required in each case to prevent lost updates under concurrent request load?
35775 reputation · 10 Jun 2023, 07:47 UTC
The default atomic accessor lock does not protect a compound invariant across multiple calls. It only guarantees that each individual getter and setter operation is atomic.
To prevent lost updates when maintaining a compound invariant (e.g., incrementing a counter), you must implement a synchronization boundary that encompasses the entire read-modify-write sequence, regardless of whether the property is atomic or nonatomic.
To confirm the performance impact, what is the expected concurrency level (e.g., peak requests per second) under which latency due to the accessor lock becomes a measurable bottleneck?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.