Sendable — apa itu, protokol keamanan thread

Penulis: IT Sectr Diterbitkan: 2026-06-18 Waktu membaca: 10 mnt

Sendable — adalah protokol Swift yang menandai tipe yang aman untuk dikirim antar thread. Saat bekerja dengan konkurensi (actor, async/await, Task), kompiler Swift memerlukan semua data yang dikirim antar konteks terisolasi untuk sesuai dengan Sendable. Ini mengecualikan pengiriman tidak sengaja tipe tidak aman yang dapat menyebabkan race condition. Protokol bertindak sebagai kontrak: tipe yang sesuai dengan Sendable menjamin tidak adanya keadaan internal yang tidak disinkronkan. Menurut WWDC 2021, protokol Sendable adalah elemen wajib dalam merancang arsitektur multi-thread yang aman.

Utama

  • Sendable — protokol yang menjamin tidak adanya race condition saat pengiriman antar thread
  • Tipe nilai (struct, enum) secara otomatis sesuai dengan Sendable jika semua propertinya adalah Sendable
  • @unchecked Sendable — mekanisme bypass untuk kelas yang keamanannya ditanggung oleh pengembang
  • Penutupan Sendable ditandai dengan atribut @Sendable yang memeriksa penangkapan variabel
  • Kompiler mengeluarkan kesalahan jika tipe non-Sendable dikirim antar konteks terisolasi

Apa itu protokol Sendable di Swift?

Sendable — adalah protokol dari perpustakaan standar Swift (SE-0302) yang menandai tipe yang aman untuk dikirim antar domain isolasi. Domain isolasi mencakup actor, tugas Task, atau konteks @MainActor. Sendable tidak berisi persyaratan — ia bertindak sebagai penanda keamanan.

Mengapa Sendable diperlukan

Sebelum Swift 5.5, pengembang dapat mengirim objek apa pun antar thread melalui DispatchQueue, dan kompiler tidak memeriksa apakah itu aman. Sendable menutup celah ini: sekarang kompiler sendiri melacak pengiriman antar thread dan memblokir yang tidak aman. Ini membuat kode konkuren lebih andal bahkan sebelum dijalankan.

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

class NonSendableClass {
    var counter: Int = 0
}

Dalam contoh, UserProfile dapat dikirim dengan aman antar thread, karena ini adalah struktur dengan properti konstan dari tipe Sendable. NonSendableClass akan menyebabkan kesalahan kompilasi saat mencoba mengirim melalui await atau ke Task.

Tipe apa yang secara default sesuai dengan Sendable

Tipe Sendable di Swift dibagi menjadi tiga kategori: tipe nilai dengan properti Sendable, kelas final dengan keadaan tidak dapat diubah, dan fungsi/penutupan yang ditandai dengan @Sendable. Kompiler secara otomatis menyimpulkan kesesuaian Sendable untuk tipe nilai.

Tipe nilai dan kesesuaian otomatis

Struct, enum dan tuple secara otomatis menjadi Sendable jika semua properti dan nilai terkaitnya juga Sendable. Ini adalah pendekatan konservatif: jika bahkan satu properti tidak sesuai dengan Sendable, seluruh tipe tidak akan dianggap aman.

TipeSendableSyarat
StructYa (tanpa indikasi eksplisit)Semua properti Sendable
EnumYa (tanpa indikasi eksplisit)Semua nilai terkait Sendable
Final classYa (dengan indikasi eksplisit)Semua properti let Sendable, tidak ada var
Non-final classTidakTidak bisa menjadi Sendable karena pewarisan

Tipe dasar

Semua tipe bawaan Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — sesuai dengan Sendable. Ini membuat komposisi tipe aman secara default. Pengembang hanya perlu memperhatikan kelas khusus.

Sendable dan kelas: @unchecked Sendable

@unchecked Sendable — adalah mekanisme yang memungkinkan kelas untuk secara eksplisit mendeklarasikan dirinya sebagai Sendable, melewati pemeriksaan kompiler. Pengembang mengambil tanggung jawab untuk keamanan thread dari kelas tersebut. Ini berguna untuk jembatan Objective-C dan struktur yang dioptimalkan.

Kapan menggunakan @unchecked Sendable

@unchecked Sendable diterapkan ketika kelas secara internal menjamin keamanan melalui kunci atau operasi atomik, tetapi kompiler tidak dapat memeriksanya secara statis. Misalnya, kelas dengan os_unfair_lock atau pthread_mutex_t — keamanan thread-nya dijamin oleh kode, tetapi Swift tidak melihatnya.

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

Gunakan @unchecked Sendable dengan hati-hati. Ini adalah sinyal yang jelas bagi pengembang lain: “Saya sudah memeriksa, ini aman”. Kesalahan dalam implementasi dapat menyebabkan race condition yang sulit dilacak. Sebelum menerapkan @unchecked, pastikan tipe tersebut benar-benar tidak dapat ditulis ulang sebagai tipe nilai.

Sendable dalam kombinasi dengan Actor

Actor dan Sendable adalah dua sisi dari koin yang sama. Actor mengisolasi keadaannya, tetapi untuk pertukaran data dengan dunia luar ia harus mengembalikan tipe Sendable. Jika metode actor mengembalikan tipe non-Sendable, kompiler mengeluarkan peringatan atau kesalahan.

Pengiriman data melalui Sendable

Ketika actor mengirim data ke kode eksternal, data ini melintasi batas isolasi. Sendable menjamin bahwa penerima dapat menggunakannya dengan aman di luar actor. Actor itu sendiri tetap terisolasi — keadaan internalnya tidak diungkapkan.

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 — adalah struktur Sendable yang hanya berisi properti let dari tipe Sendable. Pendekatan ini adalah praktik terbaik untuk mengekstrak data dari actor. Snapshot keadaan dikirim berdasarkan nilai, dan actor tidak kehilangan kendali atas keadaannya.

Fungsi dan penutupan Sendable

@Sendable — adalah atribut untuk fungsi dan penutupan yang menjamin bahwa penutupan tidak menangkap data non-Sendable dengan cara yang dapat diubah. Ketika penutupan dikirim ke Task atau metode actor, ia harus Sendable.

Pemeriksaan penangkapan dalam penutupan @Sendable

Kompiler memeriksa bahwa penutupan @Sendable tidak menangkap referensi yang dapat diubah ke kelas. Penangkapan properti let dari tipe Sendable diizinkan. Penangkapan variabel var dari tipe referensi akan menyebabkan kesalahan, karena penutupan dapat dijalankan bersamaan dengan mutasi.

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

let constant = "Safe"
var counter = 0
// counter — menangkap var memutasi penghitung, kesalahan kompilasi
performAsync { // ❌ Mutasi var yang ditangkap
    print(constant)
}

Aturannya sederhana: penutupan @Sendable hanya dapat menangkap data yang Sendable dan tidak akan dimutasi dari luar. Untuk kelas, penangkapan referensi lemah weak self diizinkan jika kelas tidak ditandai sebagai Sendable. Ini mencegah retain cycle klasik dan race condition.

Pertanyaan yang Sering Diajukan

Apa itu Sendable di Swift dengan kata sederhana?

Sendable — adalah penanda yang memberi tahu kompiler: “Tipe ini dapat dikirim dengan aman antar thread”. Struktur dan konstanta biasanya Sendable secara default, kelas — tidak, kecuali dinyatakan secara eksplisit.

Tipe apa yang secara otomatis sesuai dengan Sendable?

Tipe nilai (struct, enum) dengan properti Sendable, kelas final dengan keadaan tidak dapat diubah, serta semua tipe dasar Swift: Int, String, Double, Bool, Array, Dictionary, Optional — secara otomatis sesuai dengan Sendable.

Apa itu @unchecked Sendable?

@unchecked Sendable — adalah cara untuk mendeklarasikan kelas sebagai Sendable tanpa pemeriksaan statis kompiler. Pengembang menjamin keamanan secara mandiri, sering melalui kunci atau operasi atomik.

Mengapa Sendable diperlukan untuk Actor?

Actor mengisolasi keadaannya, tetapi saat mengembalikan data ke kode eksternal, data ini melintasi batas isolasi. Sendable menjamin bahwa penerima tidak akan menghadapi race condition saat menggunakan data ini di luar actor.

Bagaimana cara membuat kelas Sendable di Swift?

Tambahkan protokol Sendable ke kelas final yang semua propertinya adalah konstanta dari tipe Sendable. Jika kelas menggunakan kunci, @unchecked Sendable dapat diterapkan, tetapi ini memerlukan kehati-hatian.

Kesimpulan

  • Sendable — protokol penanda untuk pengiriman data yang aman antar thread
  • Tipe nilai secara otomatis sesuai dengan Sendable saat kondisi terpenuhi
  • Kelas memerlukan indikasi eksplisit Sendable atau @unchecked Sendable
  • Actor mengembalikan data ke kode eksternal hanya melalui tipe Sendable
  • @Sendable atribut penutupan memeriksa kebenaran penangkapan variabel
  • Kompiler secara statis memeriksa kesesuaian Sendable, mencegah race condition pada tahap pembuatan

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga