Swift Actors

Jul 30, 2022swiftswift-5.5

Swift 5.5 introduced a new reference type called actor that protects access to its mutable state, and is declared with the keyword actor. Actor instances can be freely shared across concurrently-executing code, and the actor itself will internally maintain synchronization.

actor BankAccount {
  let accountNumber: Int
  var balance: Double

  init(accountNumber: Int, initialDeposit: Double) {
    self.accountNumber = accountNumber
    self.balance = initialDeposit

Actors can have initializers, methods, properties, and subscripts. They can be extended and conform to protocols, be generic, and be used with generics.

The ability to protect their state from data races1 (but not necessarily free from race conditions2) is enforced statically by the Swift compiler through a set of limitations on the way in which actors and their instance members can be used, collectively called actor isolation.

  • Allow their stored instance properties to be accessed directly on self.
  • Allow cross-actor reference to immutable state from anywhere in the same module as the actor is defined.
  • Allow cross-actor reference to mutable state performed with an read-only asynchronous call.
extension BankAccount {
  func deposit(amount: Double) {
    assert(amount >= 0)
    balance = balance + amount

func checkBalance(account: BankAccount) async {
  print(await account.balance)   // okay
  await account.balance = 1000.0 // error: cross-actor property mutations are not permitted

Compile-time actor-isolation checking determines which references to actor-isolated declarations are cross-actor references, and ensures that such references use one of the two permissible mechanisms described above. This ensures that code outside of the actor does not interfere with the actor’s mutable state.

  1. A data race occurs when 2 instructions from different threads access the same memory location, at least one of these accesses is a write and there is no synchronization that is mandating any particular order among these accesses.
  2. A race condition is a semantic error. It is a flaw that occurs in the timing or the ordering of events that leads to erroneous program behavior. Many race conditions can be caused by data races, but this is not necessary.