اکتور — این چیست، انزواک داده‌ها و همروانی

نویسنده: IT Sectr منتشر شده: 2026-06-18 زمان مطالعه: 11 دقیقه

Actor — نوعی است که در Swift 5.5+ معرفی شده و مشکل مسابقه داده‌ها را در سطح زبان حل می‌کند. به علاوه قفل‌های دستی و صفوف DispatchQueue، actor به طور خودکار وضعیت خود را انزوان می‌کند و دسترسی به آن را همگام می‌کند. این به آن معنی است که دو رشته نمی‌توانند همزمان یک ویژگی از نوع actor را تغییر دهند، که شرایط مسابقه را بدون تلاش اضافی از طرف توسعه‌دهنده منتفی می‌کند. مکانیسم بر اساس مفهوم انزواک اکتور است، جایی که کامپایلر دسترسی به ویژگی‌ها و روش‌های actor را ردگیابی می‌کند. به گزارش Apple، 2025، مدل اکتور بخش بنیادین سیستم همروانی Swift است.

نکات اصلی

  • Actor — نوعی که به طور خودکار وضعیت خود را از مسابقه داده‌ها در سطح کامپایلر انزوان می‌کند
  • انزواک تضمین می‌کند که فقط یک رشته همزمان به نمونه اکتور دسترسی دارد
  • فراخوانی‌ها روش‌های actor از طریق مکانیسم async/await به صورت ناهمگبام انجام می‌شوند
  • Nonisolated امکان انصال انتخابی ازکسون ازکسون را برای اعضای منفرد actor فراهم می‌کند
  • Reentrancy ورود مجدد به actor را با جلوگیری از بلوک‌های متقابل مجاز می‌کند

Actor در Swift چیست؟

Actor — یک نوع ارجاعی مانند کلاس است، اما با حفاظت خودکار از مسابقه داده‌ها. آن در Swift 5.5 به عنوان بخشی از سیستم همروانی همراه با async/await و Task معرفی شد. Actor تضمین می‌کند که وضعیت تغییرپذیر آن هرگز بدون همگام‌سازی صریح از رشته‌های مختلف به طور همزمان خوانده یا نوشته نمی‌شود.

املای اعلام Actor

برای اعلام actor از کلمه کلیدی actor استفاده می‌شود، پس از آن اقواس می‌آید با اعضای آن. از نظر نحوی، actor مانند کلاس است، اما رفتار آن اساساً متفاوت است.

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

کامپایلر همه ویژگی‌ها و روش‌های actor را به طور خودکار انزوان می‌کند تا فقط در داخل منطقه اکتور در دسترس باشند. در صورت تلاش برای دسترسی به balance از خارج actor، اگر فراخوانی به عنوان async علامت‌گذاری نشده باشد، کامپایلر خطا خواهد داد.

انزواک داده‌ها در Actor چگونه کار می‌کند

انزواک داده‌ها — مفهوم کلیدی actor است. Actor دسترسی متقابل به وضعیت خود را از طریق مکانیسم اجراینده اکتور (actor executor) تضمین می‌کند. هر actor اجراینده مخصوص خود را دارد که تمامی مراجعات به اعضای انزوان شده آن را به طور متوالی پردازش می‌کند.

اصل کار انزواک

وقتی کد خارج از actor روش آن را فراخوان می‌کند، فراخوانی در صف انتظار اجراینده اکتور قرار می‌گیرد. Actor فقط یک وظیفه را همزمان انجام می‌دهد که عدم وجود مسابقه را تضمین می‌کند. اگر دو رشته همزمان deposit را فراخوان کنند، فراخوانی دوم منتظر تکمیل اولی می‌ماند.

swift
let account = BankAccount(initialBalance: 1000.0)
// فراخوانی ناهمگبام — از خارج actor مورد نیاز است
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()

هر فراخوانی از روش actor به await نیاز دارد، چون actor ممکن است مشغول وظیفه دیگری باشد. این یک اشتباه نیست، بلکه طراحی آگاهانه‌ای برای جلوگیری از مسابقه است. Swift به صورت ضمنی getter و setter ویژگی‌های actor را async می‌کند، بنابراین خواندن ویژگی نیز به await نیاز دارد.

تفاوت‌های اصلی Actor و کلاس

Actor و کلاس هر دو نوع ارجاعی هستند، اما رفتار آن‌ها در محیط چندرشته‌ای اساساً متفاوت است. کلاس هیچ حفاظت خودکاری در برابر مسابقه تأمین نمی‌کند، در حالی که actor آن را در سطح کامپایلر از طریق سیستم نوع جاری می‌کند.

ویژگیActorClass
حفاظت در برابر مسابقهخودکار، در سطح کامپایلرنیازمند همگام‌سازی دستی
دسترسی به ویژگی‌هافقط از طریق await از خارجمستقیم، بدون همگام‌سازی
ارث‌بریفقط از actorهای دیگرارث‌بری استاندارد کلاس
اطاعت از پروتکلمی‌تواند از پروتکل‌ها اطاعت کنداستاندارد
کاراییسرریوی پایین در انزواکبدون همگام‌سازی — سریع‌تر

ارث‌بری Actor

Actor فقط می‌تواند از دیگر actor ارث‌بری کند و نمی‌تواند از کلاس ارث‌بری کند. این به صورت آگاهانه انجام شده است، زیرا کلاس مکانیسم انزواک اکتور را ندارد و اختلاط دو مدل منجر به رفتار نامشخص می‌شد.

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

فراخوانی‌های ناهمگبام روش‌های Actor

فراخوانی‌های ناهمگبام — مکانیسم تعامل با actor از کد خارجی است. از آنجایی که actor وضعیت خود را انزوان می‌کند، هر دسترسی به اعضای آن از خارج به await نیاز دارد. این به Swift امکان می‌دهد تضمین کند که کد فراخواننده رشته را بلوک نمی‌کند و actor می‌تواند سایر درخواست‌ها را پردازش کند.

Actorهای سراسری و محلی

علاوه بر نوع‌های actor اعلام شده، Swift از actorهای سراسری پشتیبانی می‌کند — ویژگی @MainActor که کلاس‌ها، ویژگی‌ها یا روش‌ها را برای اجرا در رشته اصلی علامت‌گذاری می‌کند. این به ویژه هنگام کار با UIKit و SwiftUI مفید است.

swift
@MainActor
class ViewModel: ObservableObject {
    @Published var title: String = ""
    
    func updateTitle() {
        // این کد تضمین شده است که روی رشته اصلی اجرا شود
        title = "New Title"
    }
}

استفاده از @MainActor نیاز به فراخوانی دستی DispatchQueue.main.async را از بین می‌برد، که کد را تمیزتر و ایمن‌تر می‌کند. کامپایلر اطمینان می‌یابد که تغییر به رشته اصلی به درستی انجام می‌شود.

منطقه Nonisolated و actor-isolated

Nonisolated — کلمه کلیدی است که به شما امکان می‌دهد یک روش یا ویژگی محاسبه‌شدنی actor را به عنوان غیر انزوان علامت‌گذاری کنید. چنین اعضایی به وضعیت انزوان شدهٔ actor دسترسی ندارند، اما می‌توانند بدون await از خارج actor فراخوان شوند.

توابع Nonisolated

روش‌های Nonisolated برای محاسباتی که به وضعیت تغییرپذیر actor وابسته نیستند مفید هستند. به عنوان مثال، روش formatBalance به طور مستقیم به balance دسترسی ندارد و فقط مقدار واردی را فرمت‌دهی می‌کند — چنین روشی را می‌توان به طور ایمن nonisolated کرد.

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

اعضای nonisolated به صورت همگام اجرا می‌شوند و نیازی به await ندارند. اما نمی‌توانند به طور مستقیم ویژگی‌های انزوان شدهٔ actor را بخوانند. اگر روش nonisolated به مقداری از actor نیاز داشته باشد، باید آن را به عنوان پارامتر ارسال کند.

Reentrancy و ورود مجدد

Reentrancy — مکانیسمی است که ورود مجدد به actor را در زمان انتظار برای فراخوانی ناهمگبام مجاز می‌کند. بدون reentrancy، actor می‌توانست به طور جاویدان مسدود شود اگر یک روش آن منتظر دیگری باشد که آن هم منتظر اولی است.

Reentrancy چگونه کار می‌کند

وقتی کد داخل actor await انجام می‌دهد، actor وظیفه فعلی را متوقف می‌کند و می‌تواند دیگری را که در صف قرار دارد پردازش کند. پس از تکمیل await، وظیفه از سر گیری ادامه می‌یابد. این از deadlock جلوگیری می‌کند، اما نیازمند احتیاط است: وضعیت actor بین نقاط await می‌تواند تغییر کند.

swift
actor DataProcessor {
    var cache: [Int: String] = [:]
    
    func process(id: Int) async -> String {
        if let cached = cache[id] {
            return cached
        }
        // await — نقطه ورود مجدد
        let result = await fetchData(id: id)
        // کش ممکن است پس از await تغییر کرده باشد — مجدداً بررسی کنید
        cache[id] = result
        return result
    }
}

توسعه‌دهندگان باید reentrancy را در نظر بگیرند و وضعیت actor را پس از نقاط await بررسی کنند. یک اشتباه معمولی این است که فرض کنیم انزواک actor در طول توقف‌های ناهمگبام حفظ می‌شود. در عمل، بین await و عبارت بعدی، وضعیت می‌تواند از حالت مورد انتظار متفاوت باشد.

پرسش‌های متداول

چگونه Actor با کلاس در Swift تفاوت دارد؟

Actor به طور خودکار وضعیت خود را از مسابقه داده‌ها ایزولان می‌کند، برای دسترسی از خارج به await نیاز دارد. کلاس چنین حفاظتی را فراهم نمی‌کند — توسعه‌دهنده خود مسئول همگام‌سازی از طریق قفل‌ها یا صفوف است. Actor فقط از actor ارث‌بری می‌کند، کلاس از کلاس.

آیا می‌توان از Actor ارث‌بری کرد؟

بله، actor می‌تواند از دیگر actor ارث‌بری کند. زیرکلاس تمام ویژگی‌ها و روش‌های انزوان شدهٔ والد را دریافت می‌کند. Actor نمی‌تواند از کلاس ارث‌بری کند، زیرا کلاس‌ها مکانیسم انزواک اکتور را در سطح کامپایلر ندارند.

منطقه actor-isolated چیست؟

منطقه actor-isolated — حوزه‌ای از کد است که دسترسی مستقیم به وضعیت تغییرپذیر actor مجاز است. داخل روش‌های actor که به عنوان isolated (پیش‌فرض) علامت‌گذاری شده‌اند، می‌توان ویژگی‌ها را بدون await خواند و نوشت. کامپایلر مرزهای انزواک را بررسی می‌کند.

چگونه داده‌ها را از Actor به کد خارجی انتقال دهیم؟

داده‌ها از actor از طریق روش‌های async که نوع‌های Sendable را برمی‌گردانند، یا از طریق روش‌های nonisolated که مقادیر را به عنوان پارامتر می‌پذیرند، انتقال داده می‌شوند. همچنین می‌توان یک ویژگی async ایجاد کرد که نمایی از وضعیت actor را در قالب یک ساختار Sendable بازگرداند.

آیا Actor از ارث‌بری پروتکل پشتیبانی می‌کند؟

بله، actor می‌تواند با پروتکل‌ها مطابقت داشته باشد. اگر پروتکل شامل الزامات انزوان شده (actor-isolated) باشد، آن‌ها به طور خودکار actor-isolated می‌شوند. برای روش‌های ناهمگبام در پروتکل‌ها، می‌توان با استفاده از مارکر isolated مشخص کرد که باید روی actor مشخصی فراخوان شوند.

نتایج

  • Actor — نوع ارجاعی با انزواک خودکار داده‌ها، معرفی شده در Swift 5.5+
  • انزواک از طریق اجراینده actor کار می‌کند که درخواست‌ها را به طور متوالی پردازش می‌کند
  • دسترسی خارجی به actor نیازمند await است — این عدم وجود مسابقه را تضمین می‌کند
  • Nonisolated امکان اعلام روش‌های همگام را فراهم می‌کند که به وضعیت انزوان شده دسترسی ندارند
  • Actorهای سراسری (@MainActor) انزواک را به کل رشته اجرا انتشار می‌دهند
  • Reentrancy با اجازه ورود مجدد به actor در زمان await از deadlock جلوگیری می‌کند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید