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) }
}