Actor — co to je, izolace dat a konkurence

Autor: IT Sectr Publikováno: 2026-06-18 Doba čtení: 11 min

Actor — je typ představený v Swift 5.5+, který řeší problém závodů dat na úrovni jazyka. Na rozdíl od ručních zámků a front DispatchQueue actor automaticky izoluje svůj stav a synchronizuje k němu přístup. To znamená, že dvě vlákna nemohou současně změnit stejnou vlastnost typu actor, což eliminuje závod bez dalšího úsilí ze strany vývojáře. Mechanismus je založen na konceptu izolace actor, kdy kompilátor sleduje přístup k vlastnostem a metodám actor. Podle Apple, 2025 je model actor základní součástí systému konkurence Swift.

Hlavní body

  • Actor — typ, který automaticky izoluje svůj stav od závodů dat na úrovni kompilátoru
  • Izolace zaručuje, že k instanci actor má současně přístup pouze jedno vlákno
  • Volání metod actor jsou prováděna asynchronně mechanismem async/await
  • Nonisolated umožňuje selektivně vypnout izolaci pro jednotlivé členy actor
  • Reentrancy umožňuje opětovný vstup do actor a zabraňuje vzájemným blokádám

Co je Actor ve Swiftu?

Actor — je referenční typ, podobný třídě, ale s automatickou ochranou proti závodům dat. Byl představen v Swift 5.5 jako součást systému konkurence spolu s async/await a Task. Actor zaručuje, že jeho měnitelný stav nebude nikdy současně čten nebo zapisován z různých vláken bez explicitní synchronizace.

Syntaxe deklarace Actor

Pro deklaraci actor se používá klíčové slovo actor, za kterým následují složené závorky s jeho členy. Syntakticky actor připomíná třídu, ale chování je radikálně odlišné.

swift
actor BankAccount {
    private var balance: Double
    
    init(initialBalance: Double) {
        self.balance = initialBalance
    }
    
    func deposit(amount: Double) {
        balance += amount
    }
    
    func getBalance() -> Double {
        return balance
    }
}

Kompilátor automaticky izoluje všechny vlastnosti a metody actor tak, že jsou přístupné pouze uvnitř kontextu actor. Při pokusu o přístup k balance z vnějšku actor kompilátor vyvolá chybu, pokud volání není označeno jako async.

Jak funguje izolace dat v Actor

Izolace dat — je klíčový koncept actor. Actor zaručuje vzájemně vylučný přístup ke svému stavu prostřednictvím mechanismu vykonavatele actor (actor executor). Každý actor má vlastního vykonavatele, který zpracovává všechny přístupy k jeho izolovaným členům sekvenčně.

Princip fungování izolace

Když kód mimo actor zavolá jeho metodu, volání je umístěno do fronty vykonavatele actor. Actor provádí pouze jeden úkol současně, což zaručuje absenci závodů. Pokud dvě vlákna současně volají deposit, druhé volání čeká na dokončení prvního.

swift
let account = BankAccount(initialBalance: 1000.0)
// Asynchronní volání — vyžadováno z vnějšku actor
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()

Každé volání metody actor vyžaduje await, protože actor může být zaneprázdněn jiným úkolem. To není chyba, ale vědomý návrh, který zabraňuje závodům. Swift implicitně dělá gettery a settery vlastností actor asynchronními, takže čtení vlastnosti také vyžaduje await.

Hlavní rozdíly mezi Actor a třídou

Actor a třída jsou referenční typy, ale jejich chování ve vícevláknovém prostředí se radikálně liší. Třída neposkytuje žádnou automatickou ochranu proti závodům, zatímco actor ji vestaví na úrovni kompilátoru prostřednictvím typového systému.

CharakteristikaActorClass
Ochrana proti závodůmAutomatická, na úrovni kompilátoruVyžaduje ruční synchronizaci
Přístup k vlastnostemPouze přes await z vnějškuPřímý, bez synchronizace
DědičnostPouze od jiných actorStandardní třídní
Shoda s protokolyMůže vyhovovat protokolůmStandardní
VýkonNízké režie při izolaciBez synchronizace — rychlejší

Dědičnost Actor

Actor může dědit pouze od jiného actor a nemůže dědit od třídy. To je provedeno vědomě, protože třída nemá mechanismus izolace actor a smíchání dvou modelů by vedlo k nedefinovanému chování.

swift
actor SavingsAccount: BankAccount {
    func applyInterest(rate: Double) {
        let interest = balance * rate
        balance += interest
    }
}

Asynchronní volání metod Actor

Asynchronní volání — jsou mechanismem interakce s actor z vnějšího kódu. Protože actor izoluje svůj stav, každý přístup k jeho členům z vnějšku vyžaduje await. To umožňuje Swift zaručit, že volající kód neblokuje vlákno a actor může zpracovávat jiné požadavky.

Globální a lokální actor

Vedle deklarovaných typů actor Swift podporuje globální actor — atribut @MainActor, který označuje třídy, vlastnosti nebo metody jako prováděné na hlavním vlákně. To je užitečné zejména při práci s UIKit a SwiftUI.

swift
@MainActor
class ViewModel: ObservableObject {
    @Published var title: String = ""
    
    func updateTitle() {
        // Tento kód je zaručeně spuštěn na hlavním vlákně
        title = "New Title"
    }
}

Použití @MainActor odstraňuje nutnost ručního volání DispatchQueue.main.async, což činí kód čistším a bezpečnějším. Kompilátor kontroluje, že přepnutí na hlavní vlákno probíhá správně.

Nonisolated a actor-isolated kontexty

Nonisolated — je klíčové slovo umožňující označit metodu nebo počítanou vlastnost actor jako neizolovanou. Tyto členy nemají přístup k izolovanému stavu actor, ale mohoú být volány bez await z vnějšku actor.

Nonisolated funkce

Nonisolated metody jsou užitečné pro výpočty nezávislé na měnitelném stavu actor. Například metoda formatBalance nepřistupuje přímo k balance, pouze formátuje předanou hodnotu — takovou metodu lze bezpečně učinit nonisolated.

swift
actor BankAccount {
    private var balance: Double = 0
    
    nonisolated func formatBalance(amount: Double) -> String {
        return "$\(amount)"
    }
}

Nonisolated členy jsou prováděny synchronně a nevyžadují await. Nemohou však přímo číst izolované vlastnosti actor. Pokud nonisolated metoda potřebuje hodnotu z actor, musí být předána jako parametr.

Reentrancy a opětovný vstup

Reentrancy — je mechanismus umožňující opětovný vstup do actor během čekání na asynchronní volání. Bez reentrancy by se actor mohl navžýy zablokovat, pokud by jedna jeho metoda čekala na druhou, která na oplátku čeká na první.

Jak reentrancy funguje

Když kód uvnitř actor provádí await, actor pozastaví aktuální úkol a může zpracovat jiný zařazený do fronty. Po dokončení await je úkol obnoven. To zabraňuje deadlockům, ale vyžaduje opatrnost: stav actor mezi body await se může změnit.

swift
actor DataProcessor {
    var cache: [Int: String] = [:]
    
    func process(id: Int) async -> String {
        if let cached = cache[id] {
            return cached
        }
        // await — bod opětovného vstupu
        let result = await fetchData(id: id)
        // Mezipaměť se mohla po await změnit — znovu zkontrolujte
        cache[id] = result
        return result
    }
}

Vývojáři musí brát v úvahu reentrancy a kontrolovat stav actor po bodech await. Typickou chybou je předpoklad, že izolace actor přetrvává během asynchronních pauz. V praxi se mezi await a následujícím příkazem může stav lišit od očekávaného.

Často kladené otázky

Čím se Actor liší od třídy ve Swiftu?

Actor automaticky izoluje svůj stav od závodů dat, vyžaduje await pro přístup z vnějšku. Třída takovou ochranu neposkytuje — vývojář je sám zodpovědný za synchronizaci pomocí zámků nebo front. Actor dědí pouze od actor, třída od třídy.

Lze dědit od Actor?

Ano, actor může dědit od jiného actor. Podtřída získává všechny izolované vlastnosti a metody rodiče. Actor nemůže dědit od třídy, protože třídy nemají mechanismus izolace actor na úrovni kompilátoru.

Co je kontext actor-isolated?

Kontext actor-isolated — je oblast kódu, ve které je povolen přímý přístup k měnitelnému stavu actor. Uvnitř metod actor označených jako isolated (ve výchozím nastavení) lze vlastnosti číst a psát bez await. Kompilátor kontroluje hranice izolace.

Jak předat data z Actor vnějšímu kódu?

Data z actor se předávají prostřednictvím async-metod, které vracejí typy Sendable, nebo prostřednictvím nonisolated metod přijímajících hodnoty jako parametry. Lze také vytvořit async vlastnost, která vrátí snímek stavu actor ve formě struktury Sendable.

Podporuje Actor dědičnost protokolů?

Ano, actor může vyhovovat protokolům. Pokud protokol obsahuje izolované požadavky (actor-isolated), stanou se automaticky izolovanými pro actor. U asynchronních metod v protokolech lze pomocí markeru isolated určit, že mají být volány na konkrétním actor.

Shrnutí

  • Actor — referenční typ s automatickou izolací dat, představený v Swift 5.5+
  • Izolace funguje prostřednictvím vykonavatele actor, který zpracovává požadavky sekvenčně
  • Vnější přístup k actor vyžaduje await — to zaručuje absenci závodů
  • Nonisolated umožňuje deklarovat synchronní metody bez přístupu k izolovanému stavu
  • Globální actor (@MainActor) rozšiřují izolaci na celé vlákno provádění
  • Reentrancy zabraňuje deadlockům tím, že umožňuje opětovný vstup do actor během await

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také