Section 7/101 menit
7. Kapan Tidak Digunakan
7. Kapan Tidak Digunakan
Hindari Mutex ketika:
1. Kamu bisa menggunakan actor (async context tersedia)
swift
// JANGAN: menggunakan Mutex jika actor lebih tepat
let stateMutex = Mutex(AppState())
// ... withLock di mana-mana
// LEBIH BAIK: actor untuk async context
actor AppStateManager {
var state = AppState()
// ... methods yang jelas isolated
}
2. Operasi di dalam lock sangat lambat (memblokir thread lama)
swift
// JANGAN: melakukan async/network call di dalam withLock
mutex.withLock { _ in
// ❌ Ini memblokir thread selama lock dipegang
let data = URLSession.shared.synchronousDataTask(...) // JANGAN
}
// LEBIH BAIK: ambil state dulu, lalu lakukan operasi di luar lock
let localState = mutex.withLock { $0 }
let data = try await fetchData(using: localState)
mutex.withLock { state in
state.update(with: data)
}
3. Banyak nested lock yang dibutuhkan
swift
// JANGAN: nested mutex — deadlock risk tinggi
mutex1.withLock { _ in
mutex2.withLock { _ in // ⚠️ deadlock potential
mutex3.withLock { _ in // ⚠️⚠️ semakin dalam semakin berbahaya
}
}
}
// LEBIH BAIK: desain ulang state agar satu mutex cukup
Hindari Atomic ketika:
1. Operasi melibatkan lebih dari satu variabel
swift
// JANGAN: dua atomic yang harus konsisten — bukan atomic bersama!
let balance = Atomic(1000)
let pendingCharges = Atomic(0)
// ❌ Race condition: tidak atomik antar keduanya
let currentBalance = balance.load(ordering: .relaxed)
let pending = pendingCharges.load(ordering: .relaxed)
// Di antara dua load ini, nilai bisa berubah!
let available = currentBalance - pending
// LEBIH BAIK: gunakan Mutex untuk state yang saling terkait
let accountState = Mutex(AccountState(balance: 1000, pendingCharges: 0))
2. Logic kompleks bergantung pada nilai atomic
swift
// JANGAN: check-then-act tanpa atomic — TOCTOU race
let stockCount = Atomic(5)
if stockCount.load(ordering: .acquiring) > 0 {
// ⚠️ Stock bisa berubah setelah check tapi sebelum decrement!
stockCount.subtract(1, ordering: .releasing)
}
// LEBIH BAIK: gunakan compareExchange untuk atomic check-and-decrement
var current = stockCount.load(ordering: .relaxed)
while current > 0 {
let (exchanged, newCurrent) = stockCount.compareExchange(
expected: current,
desired: current - 1,
ordering: .acquiringAndReleasing
)
if exchanged { break } // berhasil decrement
current = newCurrent // coba lagi dengan nilai terbaru
}