Ответ
Actor — это тип данных, введенный в Swift для безопасной работы с изменяемым состоянием в конкурентном (многопоточном) коде. Он решает проблему гонок данных (data races).
Ключевой принцип: Actor изолирует свое изменяемое состояние, гарантируя, что только одна задача может получить к нему доступ в любой момент времени (взаимное исключение).
Основные особенности:
- Изоляция состояния: Все свойства и методы по умолчанию изолированы.
awaitдля доступа: Для вызова асинхронного метода или доступа к свойству actor'а извне необходимо использоватьawait. Это точка приостановки, где система решает, можно ли войти в actor.- Поддержка
Sendable: Actor сам по себе являетсяSendable, что позволяет безопасно передавать его между потоками.
Пример: BankAccount Actor
actor BankAccount {
private var balance: Double = 0
func deposit(amount: Double) {
// Внутри actor можно изменять состояние напрямую
balance += amount
}
func withdraw(amount: Double) async -> Bool {
// Проверка и изменение состояния атомарно
if balance >= amount {
balance -= amount
return true
}
return false
}
}
// Использование извне:
let account = BankAccount()
await account.deposit(amount: 100) // Требуется `await`
let success = await account.withdraw(amount: 50)
Почему это лучше мьютексов (locks)? Компилятор обеспечивает безопасность на этапе компиляции, предотвращая случайный доступ к состоянию без синхронизации.
Ответ 18+ 🔞
Смотри, вот эта штука — Actor в Swift — это типа как охранник в ночном клубе для твоих данных, когда там всё в многопоточном аду творится. Чтоб не было этой ебалы с гонками, когда десять потоков одновременно лезут в одну переменную как пьяные мартышки в банан.
Суть проще пареной репы: Actor запирает все свои изменяемые пожитки внутри себя и говорит: "Ребята, по одному, не толпитесь, блядь!". Одновременно к его внутренностям может лезть только одна задача. Остальные ждут своей очереди, как в хорошей поликлинике, сука.
Что там у него под капотом:
- Изоляция, как в ковид: Все его свойства и методы по дефолту сидят в своей комнате и не высовываются.
- Волшебное слово
await: Хочешь постучаться к actor'у извне? Говориawait, жди у моря погоды, пока он тебя впустит. Это точка, где твоя задача может приостановиться, пока actor занят другим делом. Sendableпо умолчанию: Его самого можно спокойно перекидывать между потоками — он безопасный, проверенный пацан.
Смотри, как это выглядит на практике — BankAccount:
actor BankAccount {
private var balance: Double = 0 // Это наше святое, неприкосновенное
func deposit(amount: Double) {
// Внутри actor'а делаем что хотим, мы тут хозяева
balance += amount
}
func withdraw(amount: Double) async -> Bool {
// Вся проверка и списание — одним куском, атомарно. Никто не влезет посередине.
if balance >= amount {
balance -= amount
return true
}
return false // Не хватило денег, иди работай
}
}
// А вот как с улицы этим пользоваться:
let account = BankAccount()
await account.deposit(amount: 100) // Сказал `await` и стоишь, ждёшь, пока охранник пропустит
let success = await account.withdraw(amount: 50) // Опять эта дурацкая очередь!
И главный прикол, почему это круче старых мьютексов: С мьютексами ты сам, как обезьяна с гранатой, должен был не забыть захватить lock, а потом отпустить. А тут компилятор — он как умная бабка — стоит над душой и орет: "Куда лезешь без await, а? Щас как впишу тебе ошибку компиляции!". Безопасность на уровне языка, ёпта. Не накосячишь, даже если очень захочешь.