Synchronization, Atomics and Mutex
Default choice for shared mutable state in async code Mutex<T> (Synchronization) Synchronous critical sections, Sendable Lock-free counters/flags OSAllocatedUnfairLock (Apple) Fast lock with state
NSLock, NSRecursiveLock, DispatchQueue (serial), DispatchSemaphore Legacy/Foundation synchronization
GCD (DispatchQueue.global().async, DispatchGroup) Legacy concurrency (prefer Swift Concurrency for new code)
Dependencies/cancellation between operations (legacy) Don't block in async contexts (no semaphores waiting on async work). That can deadlock the cooperative thread pool.
import Synchronization // Swift 6.0 (on newer OS versions)
final class Metrics: Sendable {
private let requests = Atomic<Int>(0)
private let state = Mutex<[String: Int]>([:])
func record(_ route: String) {
requests.add(1, ordering: .relaxed)
state.withLock { $0[route, default: 0] += 1 }
}
var total: Int { requests.load(ordering: .relaxed) }
}