Actor — o que é, isolamento de dados e concorrência

Autor: IT Sectr Publicado: 2026-06-18 Tempo de leitura: 11 min

Actor é um tipo introduzido no Swift 5.5+ que resolve o problema de condições de corrida ao nível da linguagem. Ao contrário de bloqueios manuais e filas DispatchQueue, um actor isola automaticamente o seu estado e sincroniza o acesso a ele. Isso significa que duas threads não podem modificar simultaneamente a mesma propriedade de um tipo actor, eliminando condições de corrida sem esforço adicional do desenvolvedor. O mecanismo é baseado no conceito de isolamento de actor, onde o compilador rastreia o acesso às propriedades e métodos do actor. De acordo com a Apple, 2025, o modelo de actor é uma parte fundamental do sistema de concorrência do Swift.

Pontos Principais

  • Actor é um tipo que isola automaticamente o seu estado de condições de corrida ao nível do compilador
  • O isolamento garante que apenas uma thread acede à instância do actor de cada vez
  • As chamadas aos métodos do actor executam-se assincronamente através do mecanismo async/await
  • Nonisolated permite desativar seletivamente o isolamento para membros individuais do actor
  • Reentrancy permite a reentrada num actor, prevenindo impasses

O que é um Actor em Swift?

Actor é um tipo de referência, semelhante a uma classe, mas com proteção automática contra condições de corrida. Foi introduzido no Swift 5.5 como parte do sistema de concorrência juntamente com async/await e Task. Um actor garante que o seu estado mutável nunca será lido ou escrito simultaneamente a partir de diferentes threads sem sincronização explícita.

Sintaxe de Declaração de Actor

Para declarar um actor, usa-se a palavra-chave actor seguida de chaves com os seus membros. Sintaticamente, um actor assemelha-se a uma classe, mas o seu comportamento difere radicalmente.

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

O compilador isola automaticamente todas as propriedades e métodos do actor para que sejam acessíveis apenas dentro do contexto do actor. Ao tentar aceder a balance a partir do exterior do actor, o compilador gerará um erro se a chamada não estiver marcada como async.

Como funciona o Isolamento de Dados em Actor

O isolamento de dados é o conceito-chave de um actor. Um actor garante acesso mutuamente exclusivo ao seu estado através do mecanismo do executor do actor. Cada actor tem o seu próprio executor que processa sequencialmente todos os acessos aos seus membros isolados.

Como funciona o Isolamento

Quando o código fora de um actor chama o seu método, a chamada é colocada na fila do executor do actor. O actor executa apenas uma tarefa de cada vez, garantindo a ausência de condições de corrida. Se duas threads chamarem deposit simultaneamente, a segunda chamada aguarda a conclusão da primeira.

swift
let account = BankAccount(initialBalance: 1000.0)
// Chamada assíncrona — necessária a partir do exterior do actor
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()

Cada chamada a um método do actor requer await porque o actor pode estar ocupado com outra tarefa. Isto não é um erro, mas sim uma conceção deliberada que previne condições de corrida. O Swift torna implicitamente os getters e setters das propriedades do actor async, por isso ler uma propriedade também requer await.

Principais Diferenças Entre Actor e Classe

Actor e classe são ambos tipos de referência, mas o seu comportamento num ambiente multithread difere drasticamente. Uma classe não fornece qualquer proteção automática contra condições de corrida, enquanto um actor a incorpora ao nível do compilador através do sistema de tipos.

CaracterísticaActorClasse
Proteção contra corridasAutomática, ao nível do compiladorRequer sincronização manual
Acesso a propriedadesApenas via await do exteriorDireto, sem sincronização
HerançaApenas de outros actorsHerança de classes padrão
Conformidade com protocolosPode estar em conformidade com protocolosPadrão
DesempenhoBaixa sobrecarga com isolamentoMais rápido sem sincronização

Herança de Actor

Um actor só pode herdar de outro actor e não pode herdar de uma classe. Isto é intencional porque uma classe carece do mecanismo de isolamento de actor, e misturar tipos quebraria as garantias de segurança.

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

Chamadas Assíncronas a Métodos de Actor

As chamadas assíncronas são o mecanismo para interagir com um actor a partir de código externo. Uma vez que um actor isola o seu estado, qualquer acesso aos seus membros a partir do exterior requer await. Isto permite que o Swift garanta que o código chamador não bloqueia a thread e que o actor possa processar outros pedidos.

Atores Globais e Locais

Além dos tipos de actor declarados, o Swift suporta atores globais — o atributo @MainActor, que marca classes, propriedades ou métodos como executáveis na thread principal. Isto é especialmente útil para código de UI em aplicações iOS.

swift
@MainActor
class ViewModel: ObservableObject {
    @Published var title: String = ""
    
    func updateTitle() {
        // Este código está garantido para ser executado na thread principal
        title = "New Title"
    }
}

Usar @MainActor elimina a necessidade de chamar manualmente DispatchQueue.main.async, tornando o código mais limpo e seguro. O compilador verifica que a mudança para a thread principal ocorre corretamente.

Contextos Nonisolated e Actor-Isolated

Nonisolated é uma palavra-chave que permite marcar um método ou propriedade calculada de um actor como não isolado. Esses membros não têm acesso ao estado isolado do actor, mas podem ser chamados sem await a partir do exterior do actor.

Funções Nonisolated

Os métodos nonisolated são úteis para cálculos que não dependem do estado mutável do actor. Por exemplo, o método formatBalance não acede a balance diretamente, apenas formata o valor passado — tal método é seguro para ser tornado nonisolated.

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

Os membros nonisolated executam-se sincronamente e não requerem await. No entanto, não podem ler propriedades isoladas do actor diretamente. Se um método nonisolated precisar de um valor do actor, deve ser passado como parâmetro.

Reentrancy e Reentrada

Reentrancy é um mecanismo que permite a reentrada num actor durante a espera de uma chamada assíncrona. Sem reentrancy, um actor poderia ficar bloqueado para sempre se um dos seus métodos esperasse por outro que, por sua vez, esperasse pelo primeiro.

Como funciona a Reentrada

Quando o código dentro de um actor executa await, o actor suspende a tarefa atual e pode processar outra tarefa na fila. Após a conclusão do await, a tarefa é retomada. Isto evita impasses, mas requer cuidado: o estado do actor entre pontos de await pode mudar.

swift
actor DataProcessor {
    var cache: [Int: String] = [:]
    
    func process(id: Int) async -> String {
        if let cached = cache[id] {
            return cached
        }
        // await — ponto de reentrada
        let result = await fetchData(id: id)
        // A cache pode ter mudado após await — reverificar
        cache[id] = result
        return result
    }
}

Os desenvolvedores devem ter em conta a reentrada e verificar o estado do actor após os pontos de await. Um erro típico é assumir que o isolamento do actor persiste através de pontos de suspensão assíncronos. Na prática, entre await e a instrução seguinte, o estado pode diferir do esperado.

Perguntas Frequentes

Como é que um Actor difere de uma classe em Swift?

Actor isola automaticamente o seu estado de condições de corrida, exigindo await para acesso externo. Uma classe não fornece essa proteção — o desenvolvedor é responsável pela sincronização através de bloqueios ou filas. Um actor só herda de um actor, uma classe de uma classe.

Pode-se herdar de um Actor?

Sim, um actor pode herdar de outro actor. A subclasse obtém todas as propriedades e métodos isolados do progenitor. Um actor não pode herdar de uma classe porque as classes carecem do mecanismo de isolamento de actor ao nível do compilador.

O que é um contexto actor-isolated?

Um contexto actor-isolated é uma área de código onde o acesso direto ao estado mutável do actor é permitido. Dentro dos métodos do actor marcados como isolados (por defeito), podem ler-se e escrever-se propriedades sem await. O compilador verifica os limites do isolamento.

Como passar dados de um Actor para código externo?

Os dados de um actor são passados através de métodos async que retornam tipos Sendable, ou através de métodos nonisolated que aceitam valores como parâmetros. Pode também criar-se uma propriedade async que retorna um instantâneo do estado do actor como uma estrutura Sendable.

Um Actor suporta conformidade com protocolos?

Sim, um actor pode estar em conformidade com protocolos. Se um protocolo contiver requisitos isolados (actor-isolated), estes tornam-se automaticamente isolados do actor. Para métodos assíncronos em protocolos, pode especificar-se que devem ser chamados num actor específico usando o marcador isolated.

Resumo

  • Actor é um tipo de referência com isolamento automático de dados, introduzido no Swift 5.5+
  • O isolamento funciona através de um executor de actor que processa os pedidos sequencialmente
  • O acesso externo a um actor requer await — isto garante a ausência de condições de corrida
  • Nonisolated permite declarar métodos síncronos que não acedem ao estado isolado
  • Atores globais (@MainActor) estendem o isolamento a toda a thread de execução
  • Reentrancy previne impasses ao permitir a reentrada num actor durante await

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também