Actor — vad är det, dataseparation och konkurrens

Författare: IT Sectr Publicerad: 2026-06-18 Lästid: 11 min

Actor — är en typ som introducerades i Swift 5.5+ som löser problemet med datarace på språknivå. Till skillnad från manuella lås och DispatchQueue-köer isolerar en actor automatiskt sitt tillstånd och synkroniserar åtkomst till det. Detta innebär att två trådar inte samtidigt kan ändra samma egenskap hos en actortyp, vilket eliminerar race condition utan extra ansträngning från utvecklaren. Mekanismen bygger på konceptet actorisolering, där kompilatorn spårar åtkomst till actorns egenskaper och metoder. Enligt Apple, 2025 är actormodellen en grundläggande del av Swifts konkurrenssystem.

Huvudpunkter

  • Actor — typ som automatiskt isolerar sitt tillstånd från datarace på kompilatornivå
  • Isolering garanterar att endast en tråd samtidigt har åtkomst till actorinstansen
  • Anrop av actormetoder utförs asynkront via async/await-mekanismen
  • Nonisolated gör det möjligt att selektivt stänga av isolering för enskilda medlemmar av actor
  • Reentrancy tillåter återinträde i actor och förhindrar ömsesidiga blockeringar

Vad är Actor i Swift?

Actor — är en referenstyp, liknande en klass, men med automatiskt skydd mot race conditions. Den introducerades i Swift 5.5 som en del av konkurrenssystemet tillsammans med async/await och Task. En actor garanterar att dess föränderliga tillstånd aldrig läses eller skrivs samtidigt från olika trådar utan explicit synkronisering.

Syntax för att deklarera Actor

För att deklarera en actor används nyckelordet actor, följt av måsvingar med dess medlemmar. Syntaxmässigt liknar en actor en klass, men beteendet är radikalt annorlunda.

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

Kompilatorn isolerar automatiskt alla egenskaper och metoder för actor så att de endast är tillgängliga inom actorkontexten. Ett försök att komma åt balance utanför actor kommer att orsaka ett kompileringsfel om anropet inte är markerat som async.

Hur fungerar dataseparation i Actor

Dataseparation — är det viktigaste konceptet för actor. En actor garanterar ömsesidigt uteslutande åtkomst till sitt tillstånd genom mekanismen med actorutförare (actor executor). Varje actor har sin egen utförare som bearbetar all åtkomst till dess isolerade medlemmar sekventiellt.

Funktionsprincip för isolering

När kod utanför actor anropar dess metod placeras anropet i kön hos actorutföraren. Actor utför endast en uppgift samtidigt, vilket garanterar frånvaro av race conditions. Om två trådar samtidigt anropar deposit väntar det andra anropet på att det första slutförs.

swift
let account = BankAccount(initialBalance: 1000.0)
// Asynkront anrop — krävs utifrån actor
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()

Varje anrop av en actormetod kräver await, eftersom actor kan vara upptagen med en annan uppgift. Detta är inte en bugg utan en medveten design för att förhindra race conditions. Swift gör implicit getters och setters för actoregenskaper till async, så att läsa en egenskap också kräver await.

Huvudskillnader mellan Actor och klass

Actor och klass är referenstyper, men deras beteende i en flertrådad miljö skiljer sig radikalt. En klass ger inget automatiskt skydd mot race conditions, medan en actor bygger in det på kompilatornivå genom typsystemet.

EgenskapActorClass
Skydd mot raceAutomatiskt, på kompilatornivåKräver manuell synkronisering
Åtkomst till egenskaperEndast via await utifrånDirekt, utan synkronisering
ArvEndast från andra actorsStandardklassarv
ProtokollefterlevnadKan följa protokollStandard
PrestandaLåg overhead vid isoleringUtan synkronisering — snabbare

Arv av Actor

En actor kan endast ärva från en annan actor och inte från en klass. Detta är gjort medvetet eftersom en klass inte har någon mekanism för actorisolering, och blandning av två modeller skulle leda till odefinierat beteende.

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

Asynkrona anrop av Actormetoder

Asynkrona anrop — är mekanismen för interaktion med actor från extern kod. Eftersom actor isolerar sitt tillstånd kräver varje åtkomst till dess medlemmar utifrån await. Detta gör att Swift kan garantera att den anropande koden inte blockerar tråden och att actor kan bearbeta andra förfrågningar.

Globala och lokala actors

Förutom deklarerade actortyper stödjer Swift globala actors — attributet @MainActor, som markerar klasser, egenskaper eller metoder som körda på huvudtråden. Detta är särskilt användbart när man arbetar med UIKit och SwiftUI.

swift
@MainActor
class ViewModel: ObservableObject {
    @Published var title: String = ""
    
    func updateTitle() {
        // Denna kod körs garanterat på huvudtråden
        title = "New Title"
    }
}

Användning av @MainActor eliminerar behovet av att manuellt anropa DispatchQueue.main.async, vilket gör koden renare och säkrare. Kompilatorn kontrollerar att växlingen till huvudtråden sker korrekt.

Nonisolated och actor-isolated kontexter

Nonisolated — är ett nyckelord som gör det möjligt att markera en metod eller beräknad egenskap hos en actor som oisolerad. Sådana medlemmar har inte åtkomst till actorns isolerade tillstånd, men kan anropas utan await utifrån actor.

Nonisolated funktioner

Nonisolated metoder är användbara för beräkningar som inte är beroende av actorns föränderliga tillstånd. Till exempel metoden formatBalance har inte direkt åtkomst till balance, utan formaterar bara det överförda värdet — en sådan metod kan säkert göras nonisolated.

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

Nonisolated medlemmar körs synkront och kräver inte await. De kan dock inte direkt läsa actorns isolerade egenskaper. Om en nonisolated metod behöver ett värde från actor måste det överföras som parameter.

Reentrancy och återinträde

Reentrancy — är en mekanism som tillåter återinträde i actor under väntan på ett asynkront anrop. Utan reentrancy skulle actor kunna blockeras för evigt om en av dess metoder väntar på en annan som i sin tur väntar på den första.

Hur reentrancy fungerar

När kod inuti actor utför await pausar actor den aktuella uppgiften och kan bearbeta en annan som står i kön. När await är klart återupptas uppgiften. Detta förhindrar deadlocks, men kräver försiktighet: actorns tillstånd mellan await-punkter kan förändras.

swift
actor DataProcessor {
    var cache: [Int: String] = [:]
    
    func process(id: Int) async -> String {
        if let cached = cache[id] {
            return cached
        }
        // await — återinträdespunkt
        let result = await fetchData(id: id)
        // Cachen kan ha ändrats efter await — kontrollera igen
        cache[id] = result
        return result
    }
}

Utvecklare måste ta hänsyn till reentrancy och kontrollera actorns tillstånd efter await-punkter. Ett typiskt misstag är antagandet att actorisolering bibehålls genom asynkrona pauser. I praktiken kan tillståndet mellan await och nästa sats skilja sig från det förväntade.

Vanliga frågor

Hur skiljer sig Actor från en klass i Swift?

Actor isolerar automatiskt sitt tillstånd från race conditions och kräver await för åtkomst utifrån. En klass ger inte sådant skydd — utvecklaren är själv ansvarig för synkronisering genom lås eller köer. En actor ärver endast från actor, en klass från klass.

Kan man ärva från Actor?

Ja, en actor kan ärva från en annan actor. Subklassen får alla isolerade egenskaper och metoder från föräldern. En actor kan inte ärva från en klass eftersom klasser inte har någon mekanism för actorisolering på kompilatornivå.

Vad är en actor-isolated kontext?

Actor-isolated kontext — är ett kodområde där direkt åtkomst till actorns föränderliga tillstånd är tillåten. Inuti metoder av actor som är markerade som isolated (standard) kan egenskaper läsas och skrivas utan await. Kompilatorn kontrollerar isoleringsgränserna.

Hur överför man data från Actor till extern kod?

Data från actor överförs via async-metoder som returnerar Sendable-typer, eller via nonisolated metoder som tar emot värden som parametrar. Man kan också skapa en async-egenskap som returnerar en ögonblicksbild av actorns tillstånd i form av en Sendable-struktur.

Stödjer Actor protokollarv?

Ja, en actor kan följa protokoll. Om protokollet innehåller isolerade krav (actor-isolated) blir de automatiskt actor-isolerade. För asynkrona metoder i protokoll kan man med isolated-markeringen ange att de ska anropas på en specifik actor.

Sammanfattning

  • Actor — referenstyp med automatisk dataseparation, introducerad i Swift 5.5+
  • Isolering fungerar via actorutföraren som bearbetar förfrågningar sekventiellt
  • Extern åtkomst till actor kräver await — detta garanterar frånvaro av race conditions
  • Nonisolated gör det möjligt att deklarera synkrona metoder utan åtkomst till isolerat tillstånd
  • Globala actors (@MainActor) sprider isolering till hela exekveringstråden
  • Reentrancy förhindrar deadlocks genom att tillåta återinträde i actor under await

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också