Kako sinhronizovati podatke između niti (konteksta) u iOS?
sobes.tech АИ
Одговор од АИ
Za sinhronizaciju možete koristiti sledeće mehanizme:
-
NSLock: Primitivni blokirajući mutex.
let lock = NSLock() func doSomething() { lock.lock() // Kritična sekcija koda lock.unlock() } -
NSRecursiveLock: Omogućava jednom thread-u višestruko zauzimanje blokade bez deadlock-a.
let recursiveLock = NSRecursiveLock() func recursiveFunction(level: Int) { recursiveLock.lock() if level < 3 { recursiveFunction(level: level + 1) } recursiveLock.unlock() } -
NSCondition: Omogućava thread-ovima da čekaju određeni uslov pre nego što nastave izvršavanje.
let condition = NSCondition() var dataAvailable = false func producer() { condition.lock() // Proizvodnja podataka dataAvailable = true condition.signal() // Signalizira čekajuće thread-ove condition.unlock() } func consumer() { condition.lock() while !dataAvailable { condition.wait() // Čeka dok se uslov ne ispuni } // Obrada podataka dataAvailable = false condition.unlock() } -
NSConditionLock: Mutex koji može biti zauzet samo kada je ispunjen određeni uslov-vrednost.
let conditionLock = NSConditionLock(condition: 0) let DATA_READY = 1 func producer() { conditionLock.lock(when: 0) // Zauzima kada je uslov 0 // Proizvodnja podataka conditionLock.unlock(withCondition: DATA_READY) // Oslobađa i postavlja uslov DATA_READY } func consumer() { conditionLock.lock(when: DATA_READY) // Zauzima kada je uslov DATA_READY // Obrada podataka conditionLock.unlock(withCondition: 0) // Oslobađa i postavlja uslov 0 } -
Dispatch Queues (GCD): Korišćenje sekvencijalnih dispatch redova za pristup zajedničkim resursima.
let serialQueue = DispatchQueue(label: "com.yourapp.serialQueue") var sharedResource = 0 func updateResource() { serialQueue.async { // Pristup sharedResource samo iz ove queue sharedResource += 1 } } -
NSOperationQueue: Omogućava kontrolu zavisnosti i prioriteta operacija.
let operationQueue = OperationQueue() var sharedOperationResource = 0 let operation1 = BlockOperation { // Pristup sharedOperationResource sharedOperationResource += 1 } operationQueue.addOperation(operation1) -
Actors (Swift 5.5+): Obezbeđuju izolaciju stanja, sprečavajući istovremeni pristup iz različitih konteksta.
actor Counter { private var count = 0 func increment() { count += 1 } func getCount() -> Int { return count } } let counter = Counter() Task { await counter.increment() let currentCount = await counter.getCount() print(currentCount) } -
Core Data Contexts: Za sinhronizaciju data konteksta mogu se koristiti hijerarhijski konteksti (roditelj-potomak) ili mergeChanges(fromContextDidSaveNotification:).
// Primer sa hijerarhijom (roditelj - pozadinski, potomak - UI) let privateMoc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) privateMoc.persistentStoreCoordinator = persistentStoreCoordinator let mainMoc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) mainMoc.parent = privateMoc // Primer sa mergeChanges NotificationCenter.default.addObserver(self, selector: #selector(contextDidSave(_:)), name: .NSManagedObjectContextDidSave, object: nil) @objc func contextDidSave(_ notification: Notification) { guard let savingContext = notification.object as? NSManagedObjectContext else { return } if savingContext != mainMoc { // Ako je sačuvano u nekom drugom kontekstu mainMoc.perform { mainMoc.mergeChanges(fromContextDidSave: notification) } } } -
Atomic operations: Korišćenje atomarnih primitiva (npr. iz
os/lock.h) za jednostavne operacije.
Izbor metode zavisi od složenosti zadatka, tipa podataka i zahtevanog performansa. Actors i GCD su moderni i preporučeni pristupi.