Sendable — mi ez, szál biztonsági protokoll

Szerző: IT Sectr Megjelenés: 2026-06-18 Olvasási idő: 10 perc

Sendable — egy Swift protokoll, amely megjelöli a szálak közötti átvitelre biztonságos típusokat. A konkurenciával (actor, async/await, Task) végzett munka során a Swift fordító megköveteli, hogy az izolált kontextusok között átvitt összes adat megfeleljen a Sendable-nek. Ez kizárja a nem biztonságos típusok véletlen átvitelét, amelyek adatversenyhez vezethetnek. A protokoll szerződésként működik: a Sendable-nek megfelelő típus garantálja a belső nem szinkronizált állapot hiányát. A WWDC 2021 szerint a Sendable protokoll kötelező elem a biztonságos többszálú architektúra tervezésében.

Főbb pontok

  • Sendable — protokoll, amely garantálja az adatverseny hiányát a szálak közötti átvitel során
  • Értéktípusok (struct, enum) automatikusan megfelelnek a Sendable-nek, ha összes tulajdonságuk Sendable
  • @unchecked Sendable — megkerülő mechanizmus azon osztályok számára, amelyek biztonságát a fejlesztő vállalja
  • Sendable lezárások a @Sendable attribútummal vannak jelölve, amely ellenőrzi a változók rögzítését
  • Fordító hibát ad, ha egy nem Sendable típus izolált kontextusok között kerül átvitelre

Mi a Sendable protokoll Swift-ben?

Sendable — egy protokoll a Swift szabvány könyvtárból (SE-0302), amely megjelöli a biztonságos típusokat az izolációs tartományok közötti átvitelre. Izolációs tartomány alatt actor, Task feladat vagy @MainActor kontextus értendő. A Sendable nem tartalmaz követelményeket — biztonsági jelölőként működik.

Miért van szükség Sendable-re

A Swift 5.5 előtt a fejlesztők bármilyen objektumot átvihettek a szálak között a DispatchQueue-n keresztül, és a fordító nem ellenőrizte, hogy ez biztonságos-e. Sendable bezárja ezt a rést: most a fordító maga követi nyomon a szálak közötti átvitelt és blokkolja a nem biztonságosakat. Ez megbízhatóbbá teszi a konkurens kódot még a futtatás előtt.

swift
struct UserProfile: Sendable {
    let name: String
    let age: Int
}

class NonSendableClass {
    var counter: Int = 0
}

A példában a UserProfile biztonságosan átvihető a szálak között, mert ez egy struktúra konstans Sendable típusú tulajdonságokkal. A NonSendableClass fordítási hibát okoz, ha await-en keresztül vagy Task-ban próbálják átadni.

Mely típusok felelnek meg alapértelmezettem a Sendable-nek

Sendable típusok a Swift-ben három kategóriába oszthatók: értéktípusok Sendable tulajdonságokkal, végső osztályok megváltoztathatatlan állapottal és @Sendable-lel jelölt függvények/lezárások. A fordító automatikusan következteti a Sendable-nek való megfelelt az értéktípusok számára.

Értéktípusok és automatikus megfelelés

Struct, enum és tuple automatikusan Sendable válnak, ha összes tulajdonságuk és kapcsolódó értékük is Sendable. Ez egy konzervatív megközelítés: ha még egy tulajdonság sem felel meg a Sendable-nek, az egész típus nem minősül biztonságosnak.

TípusSendableFeltétel
StructIgen (kifejezett jelölés nélkül)Minden tulajdonság Sendable
EnumIgen (kifejezett jelölés nélkül)Minden kapcsolódó érték Sendable
Final classIgen (kifejezett jelöléssel)Minden let tulajdonság Sendable, nincs var
Non-final classNemÖröklődés miatt nem lehet Sendable

Alaptípusok

Az összes beépített Swift típus — Int, String, Double, Bool, Optional, Array, Dictionary, Set — megfelel a Sendable-nek. Ez alapértelmezettem biztonságossá teszi a típus kompozíciót. A fejlesztőnek csak az egyedi osztályokra kell figyelnie.

Sendable és osztályok: @unchecked Sendable

@unchecked Sendable — egy mechanizmus, amely lehetővé teszi egy osztály számára, hogy kifejezetten Sendable-ként nyilvánítsa magát, megkerülve a fordító ellenőrzéseit. A fejlesztő vállalja a felelősséget az ilyen osztály szálbiztonságáért. Hasznos az Objective-C hidak és optimalizált struktúrák számára.

Mikor használjuk a @unchecked Sendable-t

A @unchecked Sendable akkor alkalmazandó, amikor az osztály belsőleg garantálja a biztonságot zárakon vagy atomi műveleteken keresztül, de a fordító ezt statikusan nem tudja ellenőrizni. Például egy osztály os_unfair_lock vagy pthread_mutex_t -val — a szálbiztonságot a kód biztosítja, de a Swift nem látja ezt.

swift
final class AtomicCounter: @unchecked Sendable {
    private var value: Int = 0
    private let lock = NSLock()
    
    func increment() {
        lock.lock()
        value += 1
        lock.unlock()
    }
}

A @unchecked Sendable-t óvatosan használja. Ez egyértelmű jelzés más fejlesztők számára: „Ellenőriztem, biztonságos”. A megvalósításban előforduló hiba nehezen felderíthető versenyhelyzetekhez vezethet. A @unchecked alkalmazása előtt győződjön meg arról, hogy a típus tényleg nem írható át értéktípusként.

Sendable Actorral kombinálva

Actor és Sendable ugyanazon érem két oldala. Az Actor izolálja állapotát, de a külvilággal való adatcseréhez Sendable típusokat kell visszaadnia. Ha egy actor metódus nem Sendable típust ad vissza, a fordító figyelmeztetést vagy hibát ad.

Adatok átviteli Sendable-en keresztül

Amikor az actor adatokat küld a külső kódnak, ezek az adatok átlépik az izolációs határt. Sendable garantálja, hogy a címzett biztonságosan használhatja őket az actoron kívül. Maga az actor izolált marad — belső állapota nem kerül felfedésre.

swift
struct AccountSnapshot: Sendable {
    let id: UUID
    let balance: Double
    let lastUpdated: Date
}

actor BankActor {
    private var balance: Double = 0
    
    func snapshot() async -> AccountSnapshot {
        return AccountSnapshot(
            id: UUID(),
            balance: balance,
            lastUpdated: Date()
        )
    }
}

AccountSnapshot — egy Sendable struktúra, amely csak Sendable típusok let tulajdonságait tartalmazza. Ez a megközelítés a legjobb gyakorlat az adatok actor-ból történő kinyerésére. Az állapot pillanatképe érték szerint kerül átvitelre, és az actor nem veszíti el az irányítást állapota felett.

Sendable függvények és lezárások

@Sendable — egy attribútum függvények és lezárások számára, amely garantálja, hogy a lezárás nem rögzít nem Sendable adatokat módosítható módon. Amikor egy lezárást Task-ba vagy actor metódusba küldenek, annak Sendable-nek kell lennie.

Rögzítés ellenőrzése @Sendable lezárásokban

A fordító ellenőrzi, hogy a @Sendable lezárás nem rögzít módosítható hivatkozásokat osztályokra. A Sendable típusok let tulajdonságainak rögzítése megengedett. Egy referenciatípus var változójának rögzítése hibát okoz, mert a lezárás egyidejűleg hajtódhat végre a mutációval.

swift
func performAsync(operation: @Sendable () -> Void) {
    Task {
        await operation()
    }
}

let constant = "Safe"
var counter = 0
// counter — a var rögzítése módosítja a számlálót, fordítási hiba
performAsync { // ❌ A rögzített var mutációja
    print(constant)
}

A szabály egyszerű: a @Sendable lezárás csak azokat az adatokat rögzítheti, amelyek maguk Sendable-ek és nem mutálódnak külről. Osztályok esetén a weak self gyenge hivatkozás rögzítése megengedett, ha az osztály nincs Sendable-ként jelölve. Ez megakadályozza a klasszikus retain cycle és race condition kialakulását.

Gyakran Ismételt Kérdések

Mi a Sendable a Swift-ben egyszerű szavakkal?

Sendable — egy jelölő, amely azt mondja a fordítónak: „Ez a típus biztonságosan átvihető a szálak között”. A struktúrák és konstansek általában alapértelmezettem Sendable-ek, az osztályok — nem, hacsak nincs kifejezetten jelezve.

Mely típusok felelnek meg automatikusan a Sendable-nek?

Értéktípusok (struct, enum) Sendable tulajdonságokkal, végső osztályok megváltoztathatatlan állapottal, valamint az összes alap Swift típus: Int, String, Double, Bool, Array, Dictionary, Optional — automatikusan megfelelnek a Sendable-nek.

Mi az @unchecked Sendable?

@unchecked Sendable — egy módszer egy osztály Sendable-ként való deklarálására a fordító statikus ellenőrzése nélkül. A fejlesztő önállóan garantálja a biztonságot, gyakran zárakon vagy atomi műveleteken keresztül.

Miért van szükség Sendable-re az Actor számára?

Az Actor izolálja állapotát, de az adatok külső kódnak történő visszaadásakor ezek az adatok átlépik az izolációs határt. Sendable garantálja, hogy a címzett nem ütközik versenyhelyzetekbe az adatok actoron kívüli használata során.

Hogyan lehet egy osztályt Sendable-lé tenni Swift-ben?

Adja hozzá a Sendable protokollt egy végső osztályhoz, amelynek összes tulajdonsága Sendable típusok konstansa. Ha az osztály zárakat használ, a @unchecked Sendable alkalmazható, de ez óvatosságot igényel.

Összefoglaló

  • Sendable — marker protokoll a biztonságos szálak közötti adatátvitelhez
  • Értéktípusok automatikusan megfelelnek a Sendable-nek feltételek teljesülése esetén
  • Osztályok a Sendable vagy @unchecked Sendable kifejezett jelölését igénylik
  • Actor csak Sendable típusokon keresztül ad vissza adatokat külső kódnak
  • @Sendable lezárás attribútum ellenőrzi a változók rögzítésének helyességét
  • Fordító statikusan ellenőrzi a Sendable-nek való megfelelést, megelőzve a versenyhelyzeteket az építési fázisban

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is