Hogyan szinkronizáljuk az adatok közötti adatokat a szálak között, és hogyan biztosítjuk a kontextus összhangját?
sobes.tech MI
Válasz az MI-től
Az adatok szinkronizálásához és a kontextus összhangjának biztosításához több szálon futó alkalmazásban az alábbi megközelítéseket használják:
-
NSLock / Lock: Egyszerű mutexek a kritikus kód szekciók zárolására.
import Foundation class ThreadSafeCounter { private var count: Int = 0 private let lock = NSLock() func increment() { lock.lock() defer { lock.unlock() } // A zárolás feloldásának garantálása count += 1 } func getCount() -> Int { lock.lock() defer { lock.unlock() } return count } } -
NSRecursiveLock: Lehetővé teszi a zárolás többszöri újrafogását ugyanazon a szálon.
import Foundation class RecursiveLocker { private let lock = NSRecursiveLock() func firstMethod() { lock.lock() defer { lock.unlock() } print("Első módszer") secondMethod() // Ismételt zárolás lehetséges } func secondMethod() { lock.lock() defer { lock.unlock() } print("Második módszer") } } -
NSCondition / NSConditionLock: Lehetővé teszi a szálaknak, hogy bizonyos feltétel (Condition) vagy érték (ConditionLock) teljesüléséig várjanak, mielőtt folytatnák a végrehajtást. Producer-consumer minták megvalósítására használják.
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() // Vár, amíg hely nem lesz } items.append(item) print("Hozzáadva: \(item), Aktuális buffer: \(items)") condition.signal() // Jelzi a várakozó szálaknak } func removeItem() -> Int { condition.lock() defer { condition.unlock() } while items.isEmpty { condition.wait() // Vár, amíg elem nem jelenik meg } let item = items.removeFirst() print("Eltávolítva: \(item), Aktuális buffer: \(items)") condition.signal() // Jelzi a várakozó szálaknak return item } } -
Grand Central Dispatch (GCD):
-
Serial Queues: Feladatokat egymás után hajt végre, egyenként egy adott szálon, biztosítva az erőforrások atomikus hozzáférését.
-
Concurrent Queues Barrier Flags-szel: Lehetővé teszi az olvasás párhuzamos végrehajtását, de az írási műveletek (write) kizárólagosan futnak. Ez a read-write lock modellt valósítja meg.
import Foundation class ThreadSafeArray<Element> { private var array: [Element] = [] private let queue = DispatchQueue(label: "com.mycompany.threadsafearray", attributes: .concurrent) // Párhuzamos sor func append(_ newElement: Element) { queue.async(flags: .barrier) { // Barrier íráshoz self.array.append(newElement) } } func get(at index: Int) -> Element? { var result: Element? queue.sync { // Szinkron olvasás (vagy async, ha nem számít a sorrend) if index < self.array.count { result = self.array[index] } } return result } }
-
-
Core Data Context műveletek: Minden
NSManagedObjectContextsaját, privát soros szálával rendelkezik. Az objektumokhoz és a kontextushoz való hozzáférést csak ebből a szálból szabad végezni.import CoreData // Példa a Core Data kontextus mentésére let context = // A kapott kontextus context.perform { // A kontextus saját szálán végrehajtva // Core Data objektumokkal való munka do { try context.save() } catch { // Hibakezelés } }
A módszer kiválasztása a konkrét feladattól és a teljesítménykövetelményektől függ. A GCD soros vagy párhuzamos sorokat barrier-ekkel gyakran a leghatékonyabb és legegyszerűbb megközelítés, mivel hatékony és könnyen használható. A Core Data esetében mindig a perform vagy performAndWait módszereket használja.