Как да синхронизираме данните между нишки (контекст) в iOS?
sobes.tech AI
Отговор от AI
За синхронизация можете да използвате следните механизми:
-
NSLock: Примитивен блокиращ мьютекс.
let lock = NSLock() func doSomething() { lock.lock() // Критична секция на кода lock.unlock() } -
NSRecursiveLock: Позволява на един поток многократно да захваща блокировката без дедлок.
let recursiveLock = NSRecursiveLock() func recursiveFunction(level: Int) { recursiveLock.lock() if level < 3 { recursiveFunction(level: level + 1) } recursiveLock.unlock() } -
NSCondition: Позволява на поток да чака определено условие, преди да продължи изпълнението.
let condition = NSCondition() var dataAvailable = false func producer() { condition.lock() // Производство на данни dataAvailable = true condition.signal() // Сигнализира чакащите потоци condition.unlock() } func consumer() { condition.lock() while !dataAvailable { condition.wait() // Чака, докато условието не се изпълни } // Обработка на данните dataAvailable = false condition.unlock() } -
NSConditionLock: Мьютекс, който може да бъде захванат само при изпълнение на определено условие-стойност.
let conditionLock = NSConditionLock(condition: 0) let DATA_READY = 1 func producer() { conditionLock.lock(when: 0) // Захваща при условие 0 // Производство на данни conditionLock.unlock(withCondition: DATA_READY) // Освобождава и задава условие DATA_READY } func consumer() { conditionLock.lock(when: DATA_READY) // Захваща при условие DATA_READY // Обработка на данните conditionLock.unlock(withCondition: 0) // Освобождава и задава условие 0 } -
Dispatch Queues (GCD): Използване на последователни опашки за достъп до споделени ресурси.
let serialQueue = DispatchQueue(label: "com.yourapp.serialQueue") var sharedResource = 0 func updateResource() { serialQueue.async { // Достъп до sharedResource само от тази опашка sharedResource += 1 } } -
NSOperationQueue: Позволява контролиране на зависимости и приоритети на операциите.
let operationQueue = OperationQueue() var sharedOperationResource = 0 let operation1 = BlockOperation { // Достъп до sharedOperationResource sharedOperationResource += 1 } operationQueue.addOperation(operation1) -
Actors (Swift 5.5+): Осигуряват изолация на състоянието, предотвратявайки едновременен достъп от различни контексти.
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: За синхронизиране на data contexts може да се използват йерархични контексти (родител-потомък) или mergeChanges(fromContextDidSaveNotification:).
// Пример с йерархия (родител - фонов, потомък - UI) let privateMoc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) privateMoc.persistentStoreCoordinator = persistentStoreCoordinator let mainMoc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) mainMoc.parent = privateMoc // Пример с 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 { // Ако запазването е станало не в основния контекст mainMoc.perform { mainMoc.mergeChanges(fromContextDidSave: notification) } } } -
Atomic operations: Използване на атомарни примитиви (например от
os/lock.h) за прости операции.
Изборът на метод зависи от сложността на задачата, типа данни и изискваната производителност. Actors и GCD са предпочитани съвременни подходи.