Actor — ay isang uri na ipinakilala sa Swift 5.5+ na lumulutas sa problema ng race condition ng data sa antas ng wika. Hindi tulad ng manu-manong pag-lock at DispatchQueue queues, awtomatikong inihihiwalay ng actor ang kanyang estado at nagsi-sync ng access dito. Ibig sabihin, dalawang thread ay hindi maaaring sabay na magbago ng parehong property ng isang actor-type, na nag-aalis ng race condition nang walang karagdagang pagsisikap mula sa developer. Ang mekanismo ay batay sa konsepto ng actor-isolation, kung saan sinusubaybayan ng compiler ang access sa mga property at method ng actor. Ayon sa Apple, 2025, ang actor model ay isang pangunahing bahagi ng concurrency system ng Swift.
Mga Pangunahing Punto
Actor — ay isang reference type, katulad ng isang klase, ngunit may awtomatikong proteksyon laban sa race condition. Ito ay ipinakilala sa Swift 5.5 bilang bahagi ng concurrency system kasama ng async/await at Task. Ginagarantiya ng Actor na ang kanyang nababagong estado ay hindi kailanman sabay na babasahin o susulatin mula sa iba't ibang thread nang walang tahasang synchronization.
Para magdeklara ng actor, ginagamit ang keyword na actor, na sinusundan ng mga curly braces kasama ang kanyang mga miyembro. Sa sintaks, ang actor ay kahawig ng isang klase, ngunit ang pag-uugali ay radikal na naiiba.
actor BankAccount {
private var balance: Double
init(initialBalance: Double) {
self.balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func getBalance() -> Double {
return balance
}
}
Awtomatikong inihihiwalay ng compiler ang lahat ng property at method ng actor upang ang mga ito ay ma-access lamang sa loob ng konteksto ng actor. Ang pagtatangkang i-access ang balance mula sa labas ng actor ay magdudulot ng error sa compiler kung ang tawag ay hindi minarkahan bilang async.
Paghihiwalay ng data — ay ang pangunahing konsepto ng actor. Ginagarantiya ng Actor ang mutually exclusive access sa kanyang estado sa pamamagitan ng mekanismo ng actor executor. Bawat actor ay may sariling executor na nagpoproseso ng lahat ng access sa kanyang nakahiwalay na mga miyembro nang sequensyal.
Kapag ang code sa labas ng actor ay tumawag sa kanyang method, ang tawag ay inilalagay sa pila ng actor executor. Ang actor ay nagsasagawa lamang ng isang gawain sa bawat pagkakataon, na ginagarantiya ang kawalan ng race condition. Kung dalawang thread ang sabay na tumawag ng deposit, ang pangalawang tawag ay maghihintay sa pagkumpleto ng una.
let account = BankAccount(initialBalance: 1000.0)
// Asynchronous na tawag — kinakailangan mula sa labas ng actor
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()
Bawat tawag sa actor method ay nangangailangan ng await, dahil ang actor ay maaaring abala sa ibang gawain. Ito ay hindi isang bug, kundi isang sinadyang disenyo na pumipigil sa race condition. Ginagawa ng Swift ang mga getter at setter ng actor property na implicitly async, kaya ang pagbasa ng property ay nangangailangan din ng await.
Actor at klase ay mga reference type, ngunit ang kanilang pag-uugali sa multi-threaded na kapaligiran ay radikal na naiiba. Ang klase ay hindi nagbibigay ng anumang awtomatikong proteksyon laban sa race condition, samantalang ang actor ay nagtatayo nito sa antas ng compiler sa pamamagitan ng type system.
| Katangian | Actor | Class |
|---|---|---|
| Proteksyon laban sa race | Awtomatiko, sa antas ng compiler | Nangangailangan ng manu-manong synchronization |
| Access sa mga property | Sa pamamagitan lamang ng await mula sa labas | Direkta, walang synchronization |
| Pagmamana | Mula lamang sa ibang actor | Standard na pagmamana ng klase |
| Pagsunod sa protocol | Maaaring sumunod sa mga protocol | Standard |
| Pagganap | Mababang overhead sa paghihiwalay | Walang synchronization — mas mabilis |
Ang actor ay maaari lamang magmana mula sa ibang actor at hindi maaaring magmana mula sa isang klase. Ito ay sinadyang ginawa, dahil ang klase ay walang mekanismo ng actor isolation, at ang paghahalo ng dalawang modelo ay magdudulot ng hindi tiyak na pag-uugali.
actor SavingsAccount: BankAccount {
func applyInterest(rate: Double) {
let interest = balance * rate
balance += interest
}
}
Asynchronous na tawag — ay ang mekanismo ng interaksyon sa actor mula sa panlabas na code. Dahil inihihiwalay ng actor ang kanyang estado, bawat access sa kanyang mga miyembro mula sa labas ay nangangailangan ng await. Ito ay nagpapahintulot sa Swift na garantiya na ang tumatawag na code ay hindi humaharang sa thread at ang actor ay maaaring magproseso ng iba pang mga kahilingan.
Bukod sa mga idineklarang actor type, sinusuportahan ng Swift ang global na actor — ang @MainActor attribute, na nagmamarka ng mga klase, property o method bilang isinasagawa sa pangunahing thread. Ito ay lalong kapaki-pakinabang kapag nagtatrabaho sa UIKit at SwiftUI.
@MainActor
class ViewModel: ObservableObject {
@Published var title: String = ""
func updateTitle() {
// Ang code na ito ay garantisadong tatakbo sa pangunahing thread
title = "New Title"
}
}
Ang paggamit ng @MainActor ay nag-aalis ng pangangailangan na manu-manong tumawag ng DispatchQueue.main.async, na ginagawang mas malinis at mas ligtas ang code. Sinusuri ng compiler na ang paglipat sa pangunahing thread ay nangyayari nang tama.
Nonisolated — ay isang keyword na nagpapahintulot na markahan ang isang method o computed property ng actor bilang hindi nakahiwalay. Ang mga naturang miyembro ay walang access sa nakahiwalay na estado ng actor, ngunit maaaring tawagan nang walang await mula sa labas ng actor.
Ang mga nonisolated method ay kapaki-pakinabang para sa mga kalkulasyon na hindi nakadepende sa nababagong estado ng actor. Halimbawa, ang formatBalance method ay hindi direktang pumapasok sa balance, kino-format lamang ang ipinasa na halaga — ang naturang method ay maaaring ligtas na gawing nonisolated.
actor BankAccount {
private var balance: Double = 0
nonisolated func formatBalance(amount: Double) -> String {
return "$\(amount)"
}
}
Ang mga nonisolated na miyembro ay isinasagawa nang synchronous at hindi nangangailangan ng await. Gayunpaman, hindi nila direktang mababasa ang mga nakahiwalay na property ng actor. Kung ang isang nonisolated method ay nangangailangan ng halaga mula sa actor, ito ay dapat ipasa bilang parameter.
Reentrancy — ay isang mekanismo na nagpapahintulot ng muling pagpasok sa actor habang naghihintay ng asynchronous na tawag. Kung walang reentrancy, ang actor ay maaaring permanenteng ma-block kung ang isang method nito ay naghihintay ng isa pa, na siya namang naghihintay sa una.
Kapag ang code sa loob ng actor ay nagsagawa ng await, sinuspinde ng actor ang kasalukuyang gawain at maaaring magproseso ng iba na nakapila. Pagkatapos ng await, ang gawain ay ipagpapatuloy. Ito ay pumipigil sa deadlock, ngunit nangangailangan ng pag-iingat: ang estado ng actor sa pagitan ng mga await point ay maaaring magbago.
actor DataProcessor {
var cache: [Int: String] = [:]
func process(id: Int) async -> String {
if let cached = cache[id] {
return cached
}
// await — punto ng muling pagpasok
let result = await fetchData(id: id)
// Maaaring nagbago ang cache pagkatapos ng await — suriin muli
cache[id] = result
return result
}
}
Dapat isaalang-alang ng mga developer ang reentrancy at suriin ang estado ng actor pagkatapos ng mga await point. Ang karaniwang pagkakamali ay ang pag-aakala na ang actor isolation ay nananatili sa pamamagitan ng asynchronous na pahinga. Sa pagsasagawa, sa pagitan ng await at susunod na statement, ang estado ay maaaring naiiba mula sa inaasahan.
Mga Madalas Itanong
Actor awtomatikong naghihiwalay ng kanyang estado mula sa race condition, nangangailangan ng await para sa access mula sa labas. Ang klase ay hindi nagbibigay ng ganoong proteksyon — ang developer mismo ang responsable para sa synchronization sa pamamagitan ng mga lock o queues. Ang actor ay nagmamana lamang mula sa actor, ang klase mula sa klase.
Oo, ang actor ay maaaring magmana mula sa ibang actor. Ang subclass ay tumatanggap ng lahat ng nakahiwalay na property at method ng parent. Ang actor ay hindi maaaring magmana mula sa isang klase, dahil ang mga klase ay walang mekanismo ng actor isolation sa antas ng compiler.
Actor-isolated na konteksto — ay isang lugar ng code kung saan pinapayagan ang direktang access sa nababagong estado ng actor. Sa loob ng mga method ng actor na minarkahan bilang isolated (default), ang mga property ay maaaring basahin at isulat nang walang await. Sinusuri ng compiler ang mga hangganan ng paghihiwalay.
Ang data mula sa actor ay inililipat sa pamamagitan ng async-method na nagbabalik ng Sendable type, o sa pamamagitan ng nonisolated method na tumatanggap ng mga halaga bilang parameter. Maaari ring gumawa ng async property na nagbabalik ng snapshot ng estado ng actor sa anyo ng isang Sendable structure.
Oo, ang actor ay maaaring sumunod sa mga protocol. Kung ang protocol ay naglalaman ng nakahiwalay na mga kinakailangan (actor-isolated), sila ay awtomatikong nagiging actor-isolated. Para sa mga asynchronous na method sa mga protocol, maaaring tukuyin gamit ang isolated marker na dapat silang tawagan sa isang partikular na actor.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din