Section 3/101 menit
3. Mutex\<Value\>
3. Mutex<Value>
Konsep Utama: Data dan Lock Tidak Terpisah
Inovasi utama Mutex<Value> adalah bahwa data terkunci langsung di dalam mutex — tidak ada cara untuk mengakses data tanpa lock:
swift
import Synchronization
// Value (Int) dibungkus di dalam Mutex
// Tidak ada cara akses langsung ke Int tanpa withLock
let counter = Mutex(0)
// SATU-SATUNYA cara akses: withLock
counter.withLock { value in
value += 1
}
// Baca nilai
let current = counter.withLock { $0 }
API Lengkap Mutex
swift
import Synchronization
// Inisialisasi dengan nilai awal
let mutex = Mutex(initialValue)
// withLock: akses eksklusif — parameter adalah inout
mutex.withLock { (value: inout T) in
// value adalah inout — bisa read dan write
value = newValue
let current = value
}
// withLockIfAvailable: non-blocking — returns nil jika lock tidak bisa diperoleh
let result = mutex.withLockIfAvailable { (value: inout T) -> Result in
// Dieksekusi hanya jika lock tersedia sekarang
return transform(value)
}
// result adalah Optional — nil jika lock tidak diperoleh
Mutex adalah Sendable
Mutex<Value> adalah Sendable secara otomatis (jika Value-nya Sendable), membuatnya aman untuk digunakan di seluruh isolation domain:
swift
struct AppState: Sendable {
var user: User?
var settings: Settings
}
// Mutex bisa dibagikan ke Actor, Task, dll
let sharedState = Mutex(AppState(user: nil, settings: .default))
actor NetworkService {
let state: Mutex<AppState> // OK: Mutex adalah Sendable
init(state: Mutex<AppState>) {
self.state = state
}
func updateUser(_ user: User) {
state.withLock { $0.user = user }
}
}
Nested Mutex — Deadlock Risk
swift
let mutex1 = Mutex(1)
let mutex2 = Mutex(2)
// DEADLOCK RISK: nested withLock
mutex1.withLock { _ in
mutex2.withLock { _ in // ⚠️ Bisa deadlock jika thread lain melakukan kebalikannya
// ...
}
}
// Solusi: gunakan satu Mutex untuk semua state yang saling terkait
struct CombinedState {
var value1: Int
var value2: Int
}
let combined = Mutex(CombinedState(value1: 1, value2: 2))
combined.withLock { state in
state.value1 += 1
state.value2 += 2
// Kedua operasi dalam satu lock — atomic dan tidak deadlock
}