Sobes.tech
Middle

Ist es notwendig, in diesem Fall einen asynchronen Executor zu verwenden?

sobes.tech KI

Antwort von AI

Ja, es ist notwendig.

Beim Zugriff auf actor außerhalb seines isolierten Kontexts (in diesem Fall aus dem globalen Kontext) garantiert der Compiler die Thread-Sicherheit, indem er verlangt, dass der Zugriff asynchron erfolgt.

// Protokoll zur Demonstration
protocol DataFetcher {
    func fetchData() async -> String
}

actor DataCache {
    var cache: [String: String] = [:]

    func updateCache(key: String, value: String) {
        cache[key] = value // Wird innerhalb des isolierten Kontexts des Actors ausgeführt
    }

    func cachedData(forKey key: String) -> String? {
        return cache[key] // Wird innerhalb des isolierten Kontexts des Actors ausgeführt
    }

    nonisolated func clearCacheIsolated() {
        // Diese Funktion ist als nonisolated markiert und hat keinen Zugriff auf den Zustand des Actors
        // Für den Zugriff ist ein asynchroner Aufruf erforderlich
    }
}


class DataLoader {
    let cache: DataCache // Referenz auf den Actor

    init(cache: DataCache) {
        self.cache = cache
    }

    func loadData(key: String) async -> String {
        // Asynchroner Zugriff auf den Actor von außerhalb
        if let cached = await cache.cachedData(forKey: key) {
            return cached
        }

        // ... Logik zum Laden der Daten ...
        let newData = "Data for \(key)"

        // Asynchrone Aktualisierung des Actors
        await cache.updateCache(key: key, value: newData)

        return newData
    }

    func attemptClearCacheAsync() async {
        // Asynchroner Aufruf der Actor-Methode von außerhalb
        await cache.clearCacheIsolated()
    }

    func attemptClearCacheDirect() {
        // Kompilierungsfehler:
        // Instanzmethode 'clearCacheIsolated()' isoliert durch Actor kann nicht
        // von einem nicht-isolierten Kontext aufgerufen werden
        // cache.clearCacheIsolated()
    }
}

In diesem Beispiel:

  • Die Methoden updateCache und cachedData werden innerhalb des isolierten Kontexts von DataCache ausgeführt und sind synchron innerhalb des Actors zugänglich.
  • Der Zugriff auf cache.cachedData(forKey: key) und cache.updateCache(key: key, value: newData) aus der Methode loadData (die außerhalb des actor-Kontexts liegt) erfordert das Schlüsselwort await, was auf eine asynchrone Ausführung und die Verwendung eines asynchronen Executors hinweist. Der Executor des actor ist verantwortlich für die Ausführung dieser Operationen in der Reihenfolge, die einen exklusiven Zugriff auf den Zustand des actor garantiert.
  • Die Methode clearCacheIsolated ist als nonisolated markiert, aber selbst der asynchrone Aufruf await cache.clearCacheIsolated() ist von außerhalb des actors gültig, obwohl dies in diesem Fall nicht zwingend ist, um die Thread-Sicherheit zu gewährleisten (da die Methode den Zustand des actors nicht ändert).
  • Der direkte synchrone Aufruf cache.clearCacheIsolated() aus einem nicht-isolierten Kontext (wie in attemptClearCacheDirect) führt zu einem Kompilierungsfehler, was die Notwendigkeit asynchronen Zugriffs bestätigt.

Daher ist es notwendig, um sicher mit einem actor außerhalb seines Kontexts sicher zu interagieren, asynchrone Aufrufe zu verwenden, die mit einem vom actor verwalteten asynchronen Executor ausgeführt werden.