Swift Tutorial · Swift Concurrency · Lesson 24 of 30
Swift Actors, Sendable and Data-Race Safety
Protect mutable state with actors, understand Sendable, and how the Swift 6 language mode prevents data races.
Actors
An actor is like a class whose mutable state can only be touched by one task at a time. Calls from outside
are awaited because they may have to wait their turn. Below, 1,000 concurrent increments always add up.
actor BankAccount {
private(set) var balance = 0
func deposit(_ amount: Int) { balance += amount }
}
let account = BankAccount()
await withTaskGroup(of: Void.self) { group in
for _ in 1...1_000 {
group.addTask { await account.deposit(1) }
}
}
print(await account.balance)
Output
1000
Run this on your computer — see “Get Started” for setup.
Sendable and the main actor
In the Swift 6 language mode, the compiler checks that values crossing between tasks are Sendable
(safe to share): value types made of Sendable parts, actors, and immutable final classes qualify. Sharing a
mutable class between tasks is a compile-time error, not a crash in production. UI code runs on the
@MainActor, and Swift 6.2 lets an app module make the main actor the default.
final class Counter { var value = 0 } // not Sendable
let counter = Counter()
Task.detached { counter.value += 1 } // error in Swift 6: capture of non-Sendable 'counter'
struct Order: Sendable { // a value type of Sendable parts
let id: Int
let total: Double
}
actor OrderStore {
private var orders: [Order] = []
func add(_ order: Order) { orders.append(order) }
func revenue() -> Double { orders.reduce(0) { $0 + $1.total } }
}
@MainActor
func showRevenue(_ value: Double) {
print("UI: revenue is \(value)")
}
let store = OrderStore()
await withTaskGroup(of: Void.self) { group in
for i in 1...4 {
group.addTask { await store.add(Order(id: i, total: Double(i) * 10)) }
}
}
await showRevenue(store.revenue())
Output
UI: revenue is 100.0
Run this on your computer — see “Get Started” for setup.
Test yourself
What happens in the Swift 6 language mode if you share a non-Sendable mutable class between tasks?
It crashes at runtimeThe compiler reports an errorSwift copies the objectNothing
Show answer
Answer: The compiler reports an error