Section 6/101 menit

6. Kapan Harus Digunakan

6. Kapan Harus Digunakan

Gunakan Mutex<Value> ketika:

1. State yang perlu banyak field diupdate atomik bersama

swift
// Beberapa field harus konsisten satu sama lain
struct NetworkState {
    var isConnected: Bool
    var lastError: Error?
    var reconnectAttempts: Int
}

let networkState = Mutex(NetworkState(isConnected: false, lastError: nil, reconnectAttempts: 0))

// Update semua field dalam satu lock — konsisten
networkState.withLock { state in
    state.isConnected = false
    state.lastError = connectionError
    state.reconnectAttempts += 1
}

2. Synchronous code yang tidak bisa pakai actor (tidak bisa await)

swift
// Misalnya delegate methods, init, atau synchronous path
class URLSessionManager: NSObject, URLSessionDelegate {
    private let activeRequests = Mutex([UUID: URLSessionTask]())
    
    // URLSessionDelegate method adalah synchronous — tidak bisa await actor
    func urlSession(_ session: URLSession, task: URLSessionTask, didComplete: Error?) {
        activeRequests.withLock { requests in
            requests = requests.filter { $0.value !== task }
        }
    }
}

3. Non-blocking lock attempt diperlukan

swift
let resource = Mutex(Resource())

// Coba tanpa blocking
if let result = resource.withLockIfAvailable({ $0.process() }) {
    use(result)
} else {
    // Resource sedang dipakai — coba lagi nanti atau skip
    scheduleRetry()
}

Gunakan Atomic<Value> ketika:

1. Single primitive yang diakses concurrent

swift
let activeConnectionCount = Atomic(0)

// Di setiap connection open:
activeConnectionCount.add(1, ordering: .relaxed)

// Di setiap connection close:
activeConnectionCount.subtract(1, ordering: .relaxed)

// Baca total:
let total = activeConnectionCount.load(ordering: .relaxed)

2. Lock-free flag / once

swift
let isInitialized = Atomic(false)

func initialize() {
    // Hanya inisialisasi sekali, bahkan dari concurrent threads
    let (exchanged, _) = isInitialized.compareExchange(
        expected: false,
        desired: true,
        ordering: .acquiringAndReleasing
    )
    
    guard exchanged else { return }  // sudah diinisialisasi thread lain
    
    // Lakukan inisialisasi...
    setupDatabase()
    loadConfiguration()
}

3. Performance-critical counter

swift
// Profiling atau metrics di hot path — Atomic jauh lebih cepat dari Mutex untuk ini
struct Metrics {
    let requestCount = Atomic(0)
    let errorCount = Atomic(0)
    let totalLatencyMicros = Atomic(Int64(0))
    
    func recordRequest(latencyMicros: Int64, isError: Bool) {
        requestCount.add(1, ordering: .relaxed)
        if isError { errorCount.add(1, ordering: .relaxed) }
        totalLatencyMicros.add(latencyMicros, ordering: .relaxed)
    }
    
    var averageLatency: Double {
        let count = Double(requestCount.load(ordering: .relaxed))
        let total = Double(totalLatencyMicros.load(ordering: .relaxed))
        return count > 0 ? total / count : 0
    }
}