Hoe synchroniseer je gegevens tussen threads en zorg je voor consistentie van de context?
sobes.tech AI
Antwoord van AI
Voor het synchroniseren van gegevens en het waarborgen van de consistentie van de context in een multi-threaded applicatie op iOS worden de volgende benaderingen gebruikt:
-
NSLock / Lock: Eenvoudige mutexen voor het blokkeren van kritieke secties van code.
import Foundation class ThreadSafeCounter { private var count: Int = 0 private let lock = NSLock() func increment() { lock.lock() defer { lock.unlock() } // Garant voor het losmaken van de lock count += 1 } func getCount() -> Int { lock.lock() defer { lock.unlock() } return count } } -
NSRecursiveLock: Maakt herhaalde vergrendeling mogelijk vanuit dezelfde thread.
import Foundation class RecursiveLocker { private let lock = NSRecursiveLock() func firstMethod() { lock.lock() defer { lock.unlock() } print("Eerste methode") secondMethod() // Herhaalde vergrendeling mogelijk } func secondMethod() { lock.lock() defer { lock.unlock() } print("Tweede methode") } } -
NSCondition / NSConditionLock: Laat threads wachten op een bepaalde voorwaarde (Condition) of waarde (ConditionLock) voordat ze doorgaan. Wordt gebruikt voor het implementeren van producer-consumer patronen.
import Foundation class Buffer { private var items: [Int] = [] private let condition = NSCondition() private let capacity = 5 func addItem(_ item: Int) { condition.lock() defer { condition.unlock() } while items.count == capacity { condition.wait() // Wacht tot er ruimte vrij is } items.append(item) print("Toegevoegd: \(item), Huidige buffer: \(items)") condition.signal() // Signaleer wachtende threads } func removeItem() -> Int { condition.lock() defer { condition.unlock() } while items.isEmpty { condition.wait() // Wacht tot er een element is } let item = items.removeFirst() print("Verwijderd: \(item), Huidige buffer: \(items)") condition.signal() // Signaleer wachtende threads return item } } -
Grand Central Dispatch (GCD):
-
Serial Queues: Voert taken achtereenvolgens uit, één tegelijk op een thread, wat atomair toegang tot resources garandeert.
-
Concurrent Queues met Barrier Flags: Laat lezen gelijktijdig uitvoeren, maar schrijfoperaties (write) worden exclusief uitgevoerd. Dit implementeert een read-write lock model.
import Foundation class ThreadSafeArray<Element> { private var array: [Element] = [] private let queue = DispatchQueue(label: "com.mycompany.threadsafearray", attributes: .concurrent) // Concurrerende queue func append(_ newElement: Element) { queue.async(flags: .barrier) { // Barrier voor schrijven self.array.append(newElement) } } func get(at index: Int) -> Element? { var result: Element? queue.sync { // Sync voor lezen (of async, als volgorde niet belangrijk is) if index < self.array.count { result = self.array[index] } } return result } }
-
-
Core Data Context operaties: Elke
NSManagedObjectContextheeft zijn eigen privé-seriale thread. Toegang tot objecten en de context moet alleen vanaf deze thread plaatsvinden.import CoreData // Voorbeeld van opslaan in een Core Data context let context = // Verkregen context context.perform { // Uitvoeren op de privé-thread van de context // Werken met Core Data objecten hier do { try context.save() } catch { // Foutafhandeling } }
De keuze van methode hangt af van de specifieke taak en prestatie-eisen. GCD met seriële queues of gelijktijdige queues met barrières zijn vaak de meest aanbevolen aanpak vanwege hun efficiëntie en gebruiksgemak. Voor Core Data moet je altijd de methoden perform of performAndWait gebruiken.